Vis 2 Demo  1.0
Technical illustration type real-time rendering of geometry
 All Classes Namespaces Files Functions Variables Typedefs Macros
LoaderScene.cpp
Go to the documentation of this file.
1 #include <fstream>
2 #include <string>
3 #include <sstream>
4 #include "LoaderScene.h"
5 
6 using namespace vis2;
7 
8 LoaderScene::LoaderScene(const std::string & _scene_path, const unsigned int _screen_w, const unsigned int _screen_h)
9  : scene_path(_scene_path),
10  screen_width(_screen_w), screen_height(_screen_h), backgr_col(glm::vec3(1.0f, 1.0f, 1.0f)), // viewport vars
11  view_pos(glm::vec4(0.0f, 0.0f, -1.0f, 1.0f)), view_pos_lookAt(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)), // view vectors
12  light_pos_0_init(glm::vec4(-10.0f, 10.0f, -10.0f, 1.0f)), light_col_0(glm::vec3(1.0f, 1.0f, 1.0f)), // light 0 init
13  light_pos_1_init(glm::vec4( 10.0f, -10.0f, 10.0f, 1.0f)), light_col_1(glm::vec3(1.0f, 1.0f, 1.0f)), // light 1 init
14  col_edges(glm::vec3(0.0f, 0.0f, 0.0f)), // initial edge color
15  mM_obj(glm::rotate(glm::mat4(1.0f), -90.0f, glm::vec3(1.0f, 0.0f, 0.0f))), // initial model matrix
16  counter_shell_obj(0), counter_content_obj(0), counter_separator_obj(0),// object counters
17  FBOs_ready(false) // readiness for post-processing
18 {
19  // check file extension
20  if (_scene_path.size() > 4 && !_scene_path.substr(_scene_path.size()-4).compare(".txt")) {
21 
22  // initialize loading status for shaders and shader controllers
23  for (unsigned int i = 0; i < VIS2_MAX_NR_SHADER_TYPES; i++)
24  {
25  shader_loaded[i] = false;
26  }
27  // initialize loading status for geometry objects
28  for (unsigned int i = 0; i < VIS2_SCENE_MAX_NR_SHELL_OBJ; i++)
29  {
30  shells_loaded[i] = false;
31  }
32  for (unsigned int i = 0; i < VIS2_SCENE_MAX_NR_CONTENT_OBJ; i++)
33  {
34  contents_loaded[i] = false;
35  }
36  for (unsigned int i = 0; i < VIS2_SCENE_MAX_NR_SEPARATOR_OBJ; i++)
37  {
38  separators_loaded[i] = false;
39  }
40  // initialize neighborhood service
42  }
43  else
44  {
45  std::cout << "The valid file extension for a scene file is \"txt\"!" << std::endl;
46  system("PAUSE");
47  exit(-1);
48  }
49 }
50 
52 {
53  // delete shaders and shader controllers
54  for (unsigned int i = 0; i < VIS2_MAX_NR_SHADER_TYPES; i++)
55  {
56  if (shader_loaded[i])
57  {
58  delete shaders[i];
59  delete shader_ctrls[i];
60  }
61  }
62 
63  // delete drawable objects
64  for (unsigned int i = 0; i < counter_shell_obj; i++)
65  {
66  if (shells_loaded[i])
67  {
68  delete loaders_shell[i];
69  delete textures_shell[i];
70  delete shells[i];
71  }
72  }
73  for (unsigned int i = 0; i < counter_content_obj; i++)
74  {
75  if (contents_loaded[i])
76  {
77  delete loaders_content[i];
78  delete textures_content[i];
79  delete contents[i];
80  }
81  }
82  for (unsigned int i = 0; i < counter_separator_obj; i++)
83  {
84  if (separators_loaded[i])
85  {
86  delete loaders_separator[i];
87  delete textures_separator[i];
88  delete separators[i];
89  }
90  }
91 
92  // delete neighborhood service
93  delete neighb_rec_Ptr;
94 
95  // delete FBOs
96  delete fbo_0;
97  for (unsigned int i = 0; i < VIS2_SCENE_NR_FBOS_EDF; i++)
98  {
99  delete fbos_EDF[i];
100  }
101  for (unsigned int i = 0; i < VIS2_SCENE_NR_FBOS_SMF; i++)
102  {
103  delete fbos_SMF[i];
104  }
105  for (unsigned int i = 0; i < VIS2_SCENE_NR_FBOS_DPS; i++)
106  {
107  delete fbos_DPS[i];
108  }
109  for (unsigned int i = 0; i < VIS2_SCENE_NR_FBOS_DPSB; i++)
110  {
111  delete fbos_DPSB[i];
112  }
113 
114  // delete FBO quads
115  if (FBOs_ready)
116  {
117  if (shaderEDFLoaded())
118  {
119  for (unsigned int i = 0; i < VIS2_SCENE_NR_FBOS_EDF; i++)
120  {
121  delete quads_EDF[i];
122  }
123  }
124  if (shaderSMFLoaded())
125  {
126  for (unsigned int i = 0; i < VIS2_SCENE_NR_QUADS_SMF; i++)
127  {
128  delete quads_SMF[i];
129  }
130  }
131  if (shaderDPSBLoaded()) delete quad_DPSB_Ptr;
134  }
135 
136 }
137 
138 
140 {
141 
142  std::cout << "Loading Scene File from ...\"" << scene_path << "\"." << std::endl;
143  std::FILE *f;
144 
145  // ------------------------------- SHADERS ----------------------------------- //
146 
147  // open file
148  fopen_s(&f,scene_path.c_str(),"r");
149  if(!f)
150  {
151  std::cout << "Failed to open file \"" << scene_path << "\" !" << std::endl;
152  system("PAUSE");
153  exit(-1);
154  }
155 
156  // read and save content
157  parseShaders(f);
158 
159  // close file
160  if (f)
161  std::fclose(f);
162 
163  // ------------------------------- ENVIRONMENT ------------------------------- //
164 
165  fopen_s(&f,scene_path.c_str(),"r");
166  if(!f)
167  {
168  std::cout << "Failed to open file \"" << scene_path << "\" !" << std::endl;
169  system("PAUSE");
170  exit(-1);
171  }
172 
173  parseEnvironment(f);
174 
175  if (f)
176  std::fclose(f);
177 
178  // pass the environment variables to the shader controllers that need them
180  {
186  glm::vec3(view_pos_lookAt.x, view_pos_lookAt.y, view_pos_lookAt.z));
187  }
189  {
195  glm::vec3(view_pos_lookAt.x, view_pos_lookAt.y, view_pos_lookAt.z));
197  }
199  {
201  }
203  {
204  shader_ctrls[VIS2_SHADER_TYPE_COMPLEX_BLEND]->setBlendAllParams(glm::vec3(1.0f, 1.0f, 1.0f));
205  }
206 
207  // --------------------------------- GEOMETRY -------------------------------- //
208  fopen_s(&f,scene_path.c_str(),"r");
209  if(!f)
210  {
211  std::cout << "Failed to open file \"" << scene_path << "\" !" << std::endl;
212  system("PAUSE");
213  exit(-1);
214  }
215 
216  parseGeometry(f);
217 
218  if (f)
219  std::fclose(f);
220 
221  // --------------------------------- NEIGHBORS ------------------------------- //
222  fopen_s(&f,scene_path.c_str(),"r");
223  if(!f)
224  {
225  std::cout << "Failed to open file \"" << scene_path << "\" !" << std::endl;
226  system("PAUSE");
227  exit(-1);
228  }
229 
230  parseNeighbors(f);
231 
232  if (f)
233  std::fclose(f);
234 
235  // --------------------- PREPARE FOR RENDERING ------------------------------- //
236 
237  setupDrawing();
238 
239  return 0;
240 }
241 
243 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
244 // %% ------------------------------ UPDATE -------------------------------- %% //
245 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
247 
248 void LoaderScene::updateScene(glm::mat4 & _modelMatrix)
249 {
250  // update lights
251  this->light_pos_0 = _modelMatrix * light_pos_0_init;
252  this->light_pos_1 = _modelMatrix * light_pos_1_init;
253 
254  // update geometry
255  for (unsigned int i = 0; i < counter_shell_obj; i++)
256  {
257  if (shells_loaded[i])
258  shells[i]->updateModelMatrix(_modelMatrix * shells_mM[i]);
259  }
260  for (unsigned int i = 0; i < counter_content_obj; i++)
261  {
262  if (contents_loaded[i])
263  contents[i]->updateModelMatrix(_modelMatrix * contents_mM[i]);
264  }
265  for (unsigned int i = 0; i < counter_separator_obj; i++)
266  {
267  if (separators_loaded[i])
268  separators[i]->updateModelMatrix(_modelMatrix * separators_mM[i]);
269  }
270 }
271 
273 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
274 // %% -------------------------------- DRAW -------------------------------- %% //
275 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
277 
278 void LoaderScene::drawScene( bool _mouse_right_click, float _mouse_x, float _mouse_y,
279  bool _b_with_pp, bool _b_debug_mode, unsigned int _debug_pass)
280 {
281  unsigned int counter_neighb_sel = 0;
282  // %%%%%%%%%%%%%%%%%%%%%%%%%% DRAW TO TEXTURE %%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
283  if (FBOs_ready && _b_with_pp)
284  {
285  // ======== 0. PASS -> for object SELECTION =========================== //
286  glDisable(GL_CULL_FACE);
288  // draw contents
289  for (unsigned int i = 0; i < counter_content_obj; i++)
290  {
291  if (contents_loaded[i])
293  }
294  // get user selection
295  if (_mouse_right_click)
296  {
297  GLfloat selectedCol[4];
298  glReadPixels(int(_mouse_x * screen_width),int(_mouse_y * screen_height),1,1,GL_RGBA, GL_FLOAT, selectedCol);
299  selected_col = glm::vec3(selectedCol[0], selectedCol[1], selectedCol[2]);
300  }
302  glEnable(GL_CULL_FACE);
303 
304  // ============= 1A. PASS -> detection of HORIZONTAL EDGES ============ //
309 
310  // ============== 1B. PASS -> detection of VERTICAL EDGES ============= //
316 
317  // ============== 1C. PASS -> HORIZONTAL FILTERING of edges ============ //
320  shader_ctrls[VIS2_SHADER_TYPE_BLUR_H]->setBlurParams(1,3,11); // Gaussian blur
323 
324  // ============== 1D. PASS -> VERTICAL FILTERING of edges ============== //
327  shader_ctrls[VIS2_SHADER_TYPE_BLUR_V]->setBlurParams(1,3,11); // Gaussian blur
330 
331  // ============== 2A. PASS -> MASKING of SELECTION ===================== //
335  shader_ctrls[VIS2_SHADER_TYPE_MASK]->setMaskingParams(selected_col, backgr_col, 0.03f, 0); // no prev pass texture
338 
339  // ============== 2B. PASS -> MASKING of NEIGHBORS ===================== //
340  glm::vec3 selected_col_id = getSelectedColorId(selected_col, 0.03f); // correct small irregularities in the picked color
341  if (selected_col_id.r != backgr_col.r || selected_col_id.g != backgr_col.g || selected_col_id.b != backgr_col.b)
342  {
343  for (unsigned int i = 0; i < counter_content_obj; i++)
344  {
345  // look for neighbors
346  if (contents_loaded[i])
347  {
348  glm::vec3 tmp_col = contents[i]->getIdColor();
349  if (neighb_rec_Ptr->isNeighborOf(selected_col_id, tmp_col) && counter_neighb_sel <= VIS2_SCENE_MAX_NR_MASKED_NEIGHB)
350  {
351  counter_neighb_sel++;
352  if (counter_neighb_sel == 1)
353  {
355  shader_ctrls[VIS2_SHADER_TYPE_MASK]->setMaskingParams(tmp_col, backgr_col, 0.03f, 0); // NO prev pass texture
358  }
359  else
360  {
361  fbos_SMF[counter_neighb_sel]->bindFramebufferObject(backgr_col.r, backgr_col.g, backgr_col.b, 0.0f);
362  shader_ctrls[VIS2_SHADER_TYPE_MASK]->assignTexture(fbos_SMF[counter_neighb_sel - 1]->getFBOColorTexture(), VIS2_TEXTURE_1);
363  shader_ctrls[VIS2_SHADER_TYPE_MASK]->setMaskingParams(tmp_col, backgr_col, 0.03f, 1); // USE prev pass texture
365  fbos_SMF[counter_neighb_sel]->releaseFramebufferObject();
366  }
367  }
368  }
369 
370  }
371  }
372  // ============== 2C. PASS -> BLURRING OF SELECTION MASK HORIZONTAL ==== //
375  shader_ctrls[VIS2_SHADER_TYPE_BLUR_H]->setBlurParams(0,3,11); // distance blur
378 
379  // ============== 2D. PASS -> BLURRING OF SELECTION MASK VERTICAL ===== //
382  shader_ctrls[VIS2_SHADER_TYPE_BLUR_V]->setBlurParams(0,3,11); // distance blur
385 
386  glDisable(GL_CULL_FACE);
387  // ============== 3A. PASS -> RENDER SHELL OBJECTS WITH PHONG ========= //
390  {
391  for (unsigned int i = 0; i < counter_shell_obj; i++)
392  {
393  if (shells_loaded[i])
394  {
397  }
398  }
399  }
401 
402  // ============== 3B. PASS -> PEEL 1. LAYER SHELL OBJECTS ============= //
405  {
406  for (unsigned int i = 0; i < counter_shell_obj; i++)
407  {
408  if (shells_loaded[i])
409  {
413  }
414  }
415  }
417 
418  // ============== 3C. PASS -> PEEL 2. LAYER SHELL OBJECTS ============= //
420  if (shader_loaded[VIS2_SHADER_TYPE_DEPTH_PEEL])
421  {
422  for (unsigned int i = 0; i < counter_shell_obj; i++)
423  {
424  if (shells_loaded[i])
425  {
429  }
430  }
431  }
433  glEnable(GL_CULL_FACE);
434 
435  // ============== 4A. PASS -> BLEND ALL PEELED LAYERS of the shell ==== //
442 
443  // ============== 4B. PASS -> render the SELECTED object PHONG ======== //
444  unsigned int counter_selected_obj = 0;
445  for (unsigned int i = 0; i < counter_content_obj; i++)
446  {
447  if (contents_loaded[i])
448  {
449  glm::vec3 tmp_col = contents[i]->getIdColor();
450  if (tmp_col.r == selected_col_id.r && tmp_col.g == selected_col_id.g && tmp_col.b == selected_col_id.b)
451  {
452  counter_selected_obj++;
453  // bind buffer after 1. found object
454  if (counter_selected_obj == 1)
456  // render
459  }
460  }
461  }
462  // render also the separators of the same color id as the selected object(s)
463  if (counter_selected_obj > 0)
464  {
465  for (unsigned int i = 0; i < counter_separator_obj; i++)
466  {
467  if (separators_loaded[i])
468  {
469  glm::vec3 tmp_col = separators[i]->getIdColor();
470  if (tmp_col.r == selected_col_id.r && tmp_col.g == selected_col_id.g && tmp_col.b == selected_col_id.b)
471  {
474  }
475  }
476  }
477  }
478  if (counter_selected_obj > 0)
480 
481  // ============== 5A. PASS -> BLEND ALL TO BACKBUFFER ================= //
485  shader_ctrls[VIS2_SHADER_TYPE_COMPLEX_BLEND]->assignTexture(fbos_SMF[counter_neighb_sel]->getFBOColorTexture(), VIS2_TEXTURE_3);
488 
489  }
490  // %%%%%%%%%%%%%%%%%%%%% DRAW GEOMETRY TO BACKBUFFER %%%%%%%%%%%%%%%%%%%%%% //
491  else
492  {
493  // assign textures to the shader controllers and render
495  {
496  for (unsigned int i = 0; i < counter_content_obj; i++)
497  {
498  if (contents_loaded[i])
499  {
502  }
503  }
504 
505  for (unsigned int i = 0; i < counter_shell_obj; i++)
506  {
507  if (shells_loaded[i])
508  {
511  }
512  }
513 
514  }
515  }
516 
517  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEBUG %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
518  if (FBOs_ready && _b_with_pp && _b_debug_mode)
519  {
520  // draw the quad for texture visualization
521  switch(_debug_pass)
522  {
523  case 0:
525  break;
526  case 1:
528  break;
529  case 2:
531  break;
532  case 3:
534  break;
535  case 4:
537  break;
538  default:
540  break;
541  }
543  }
544 
545 }
546 
548 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
549 // %% --------------------------- PARSE SHADERS ---------------------------- %% //
550 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
552 
553 void LoaderScene::parseShaders(std::FILE* _f)
554 {
556  std::ifstream file_stream(_f);
557  std::string file_line;
558  while (!file_stream.eof())
559  {
560  std::getline(file_stream, file_line);
561  // ------------------------ EXTRACT SHADERS ----------------------- //
562  // Example SHADER:
563  // #<object type> : #shader
564  // <shader type> : 8 (see ShaderController.h)
565  // <vertex shader> : _resources/Shader/text_filter_vert.glsl
566  // <geometry shader>: _resources/Shader/text_filter_geom.glsl OR NONE
567  // <fragment shader>: _resources/Shader/solid_color_mask_frag.glsl
568  if (!file_line.substr(0,7).compare("#shader"))
569  {
570  std::string shader_type;
571  std::string vertex_shader_path;
572  std::string geometry_shader_path;
573  std::string fragment_shader_path;
574 
575  std::getline(file_stream, shader_type);
576  std::getline(file_stream, vertex_shader_path);
577  std::getline(file_stream, geometry_shader_path);
578  std::getline(file_stream, fragment_shader_path);
579 
580  string2Shader(shader_type, vertex_shader_path, geometry_shader_path, fragment_shader_path);
581  }
582  }
583 
584 }
585 
586 
587 void LoaderScene::string2Shader( const std::string & _shader_type,
588  const std::string & _vertex_shader_path,
589  const std::string & _geometry_shader_path,
590  const std::string & _fragment_shader_path)
591 {
592  if (_shader_type.empty() ||
593  _vertex_shader_path.empty() || _vertex_shader_path.size() < 5 ||
594  _geometry_shader_path.empty() || _geometry_shader_path.size() < 4 ||
595  _fragment_shader_path.empty() || _fragment_shader_path.size() < 5)
596  return;
597 
598  // extract type
599  unsigned int type;
600  std::stringstream type_ss(_shader_type);
601  if ((type_ss>>type).fail())
602  return;
603 
604  // create shader and its controller
605  if (type >= 0 && type < VIS2_MAX_NR_SHADER_TYPES)
606  {
607  shaders[type] = new vis2::Shader(_vertex_shader_path, _fragment_shader_path);
608  shader_ctrls[type] = new vis2::ShaderController(shaders[type], type);
609  shader_loaded[type] = true;
610  std::cout << "SHADER TYPE " << type << " loaded." << std::endl;
611  }
612 }
613 
615 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
616 // %% ------------------------- PARSE ENVIRONMENT -------------------------- %% //
617 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
619 
620 void LoaderScene::parseEnvironment( std::FILE* _f)
621 {
622  unsigned int counter_lights = 0;
623 
624  // file->stream
625  std::ifstream file_stream(_f);
626  std::string file_line;
627  while (!file_stream.eof())
628  {
629  std::getline(file_stream, file_line);
630  if (!file_line.substr(0,13).compare("#backgr_color"))
631  {
632  std::string str_color;
633  std::getline(file_stream, str_color);
634  this->backgr_col = string2Vec3(str_color);
635  }
636  else if (!file_line.substr(0,11).compare("#viewer_pos"))
637  {
638  std::string str_pos;
639  std::getline(file_stream, str_pos);
640  glm::vec3 pos_inhomog = string2Vec3(str_pos);
641  this->view_pos = glm::vec4(pos_inhomog.x, pos_inhomog.y, pos_inhomog.z, 1.0f);
642  }
643  else if (!file_line.substr(0,15).compare("#viewer_look_at"))
644  {
645  std::string str_look_at;
646  std::getline(file_stream, str_look_at);
647  glm::vec3 look_at_inhomog = string2Vec3(str_look_at);
648  this->view_pos_lookAt = glm::vec4(look_at_inhomog.x, look_at_inhomog.y, look_at_inhomog.z, 1.0f);
649  }
650  else if (!file_line.substr(0,6).compare("#light"))
651  {
652  // scip the third light ...
653  if (counter_lights > 1)
654  continue;
655  // otherwise parse
656  std::string str_pos;
657  std::string str_col;
658  std::getline(file_stream, str_pos);
659  std::getline(file_stream, str_col);
660  if (counter_lights == 0)
661  {
662  glm::vec3 light_0_pos_inhomog = string2Vec3(str_pos);
663  this->light_pos_0_init = glm::vec4(light_0_pos_inhomog.x, light_0_pos_inhomog.y, light_0_pos_inhomog.z, 1.0f);
664  this->light_col_0 = string2Vec3(str_col);
665  }
666  else
667  {
668  glm::vec3 light_1_pos_inhomog = string2Vec3(str_pos);
669  this->light_pos_1_init = glm::vec4(light_1_pos_inhomog.x, light_1_pos_inhomog.y, light_1_pos_inhomog.z, 1.0f);
670  this->light_col_1 = string2Vec3(str_col);
671  }
672  counter_lights++;
673  }
674  else if (!file_line.substr(0,11).compare("#edge_color"))
675  {
676  std::string str_color;
677  std::getline(file_stream, str_color);
678  this->col_edges = string2Vec3(str_color);
679  }
680  }
681 }
682 
683 glm::vec3 LoaderScene::string2Vec3(const std::string & _line)
684 {
685  // prepare a container for the floats
686  glm::vec3 values = glm::vec3(0.0f, 0.0f, 0.0f);
687 
688  // open a string stream
689  std::stringstream line_ss(_line);
690 
691  // split the string along the SPACE delimiter
692  std::string str_item;
693  unsigned int counter = 0;
694  while(std::getline(line_ss,str_item,' ') && counter < 3)
695  {
696  float num;
697  std::stringstream item_ss(str_item);
698  if (!(item_ss>>num).fail())
699  {
700  values[counter] = num;
701  counter++;
702  }
703  }
704 
705  return values;
706 }
707 
708 float LoaderScene::string2Float(const std::string & _line)
709 {
710  float result = 0.0f;
711 
712  float num;
713  std::stringstream line_ss(_line);
714  if (!(line_ss>>num).fail())
715  result = num;
716 
717  return result;
718 }
719 
721 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
722 // %% --------------------------- PARSE GEOMETRY --------------------------- %% //
723 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
725 
726 
727 void LoaderScene::parseGeometry( std::FILE* _f)
728 {
729  // file->stream
730  std::ifstream file_stream(_f);
731  std::string file_line;
732  while (!file_stream.eof())
733  {
734  std::getline(file_stream, file_line);
735  // ------------------------ EXTRACT GEOMETRY ---------------------- //
736  // Example GEOMETRY:
737  // #<object type> : #shell OR #content
738  // <name> : shell
739  // <geometry> : _resources/Models/simple/shell.obj
740  // <diff texture> : _resources/Textures/simple/shell.jpg
741  // <scale> : 0.1
742  // <color> : 0.4 0.0 0.0
743  if (!file_line.substr(0,6).compare("#shell"))
744  {
745  std::string object_name;
746  std::string geometry_path;
747  std::string diff_texture_path;
748  std::string scale;
749  std::string object_color;
750 
751  std::getline(file_stream, object_name);
752  std::getline(file_stream, geometry_path);
753  std::getline(file_stream, diff_texture_path);
754  std::getline(file_stream, scale);
755  std::getline(file_stream, object_color);
756 
757  string2Geometry( VIS2_SCENE_OBJECT_TYPE_SHELL, object_name, geometry_path, diff_texture_path, scale, object_color);
758  }
759  else if (!file_line.substr(0,8).compare("#content"))
760  {
761  std::string object_name;
762  std::string geometry_path;
763  std::string diff_texture_path;
764  std::string scale;
765  std::string object_color;
766 
767  std::getline(file_stream, object_name);
768  std::getline(file_stream, geometry_path);
769  std::getline(file_stream, diff_texture_path);
770  std::getline(file_stream, scale);
771  std::getline(file_stream, object_color);
772 
773  string2Geometry( VIS2_SCENE_OBJECT_TYPE_CONTENT, object_name, geometry_path, diff_texture_path, scale, object_color);
774  }
775  else if (!file_line.substr(0,10).compare("#separator"))
776  {
777  std::string object_name;
778  std::string geometry_path;
779  std::string diff_texture_path;
780  std::string scale;
781  std::string object_color;
782 
783  std::getline(file_stream, object_name);
784  std::getline(file_stream, geometry_path);
785  std::getline(file_stream, diff_texture_path);
786  std::getline(file_stream, scale);
787  std::getline(file_stream, object_color);
788 
789  string2Geometry( VIS2_SCENE_OBJECT_TYPE_SEPARATOR, object_name, geometry_path, diff_texture_path, scale, object_color);
790  }
791 
792  }
793 
794  std::cout << "\n\tNR SHELLS: " << counter_shell_obj << std::endl;
795  std::cout << "\tNR CONTENTS: " << counter_content_obj << std::endl;
796  std::cout << "\tNR SEPARATORS: " << counter_separator_obj << std::endl;
797 
798 }
799 
800 void LoaderScene::string2Geometry( const unsigned int _type,
801  const std::string & _object_name,
802  const std::string & _geometry_path,
803  const std::string & _diff_texture_path,
804  const std::string & _scale,
805  const std::string & _object_color)
806 {
807  if (_type != VIS2_SCENE_OBJECT_TYPE_SHELL &&
810  return;
811 
812  if (_object_name.empty() ||
813  _geometry_path.empty() || _geometry_path.size() < 5 ||
814  _diff_texture_path.empty() || _diff_texture_path.size() < 5 ||
815  _scale.empty() || _object_color.empty())
816  return;
817 
818  // copy name
819  char* obj_name_copy = new char[_object_name.size()+1];
820  sprintf_s(obj_name_copy, _object_name.size()+1, "%s", _object_name.c_str());
821  // extract scale
822  float obj_scale = string2Float(_scale);
823  // extract color
824  const glm::vec3 obj_color = string2Vec3(_object_color);
825 
826 
828  {
829  // calculate object model matrix
830  shells_mM[counter_shell_obj] = glm::scale(mM_obj, glm::vec3(obj_scale, obj_scale, obj_scale));
831  // create loader
832  loaders_shell[counter_shell_obj] = new vis2::LoaderOBJ(_geometry_path);
833  // get texture
834  textures_shell[counter_shell_obj] = new vis2::Texture(_diff_texture_path);
835  // create drawable object
836  shells[counter_shell_obj] = new vis2::ModelMultiTextured( obj_name_copy,
837  obj_color,
838  this->col_edges,
840  loaders_shell[counter_shell_obj],
844  // mark it as loaded
846 
847  std::cout << counter_shell_obj << ": Loaded SHELL object \"" << shells[counter_shell_obj]->getIdName() << "\"." << std::endl;
848  counter_shell_obj++;
849  }
851  {
852  // calculate object model matrix
853  contents_mM[counter_content_obj] = glm::scale(mM_obj, glm::vec3(obj_scale, obj_scale, obj_scale));
854  // create loader
855  loaders_content[counter_content_obj] = new vis2::LoaderOBJ(_geometry_path);
856  // get texture
857  textures_content[counter_content_obj] = new vis2::Texture(_diff_texture_path);
858  // create drawable object
860  obj_color,
861  this->col_edges,
863  loaders_content[counter_content_obj],
867  // mark it as loaded
869 
870  std::cout << counter_content_obj << ": Loaded CONTENTS object \"" << contents[counter_content_obj]->getIdName() << "\"." << std::endl;
871  counter_content_obj++;
872  }
874  {
875  // calculate object model matrix
876  separators_mM[counter_separator_obj] = glm::scale(mM_obj, glm::vec3(obj_scale, obj_scale, obj_scale));
877  // create loader
879  // get texture
880  textures_separator[counter_separator_obj] = new vis2::Texture(_diff_texture_path);
881  // create drawable object
883  obj_color,
884  this->col_edges,
886  loaders_separator[counter_separator_obj],
890  // mark it as loaded
892 
893  std::cout << counter_separator_obj << ": Loaded SEPARATOR object \"" << separators[counter_separator_obj]->getIdName() << "\"." << std::endl;
894  counter_separator_obj++;
895  }
896 
897 }
898 
900 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
901 // %% --------------------------- PARSE NEIGHBORS -------------------------- %% //
902 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
904 
905 void LoaderScene::parseNeighbors( std::FILE* _f)
906 {
907  // file->stream
908  std::ifstream file_stream(_f);
909  std::string file_line;
910  while (!file_stream.eof())
911  {
912  std::getline(file_stream, file_line);
913  // -------------- EXTRACT NEIGHBORHOOD RELATIONSHIPS -------------- //
914  // Example NEIGHBORHOOD:
915  // #<object type> : #neighbors
916  // <object name> : inside_1
917  // <neighbors list> : inside_2 inside_3 OR NONE
918  if (!file_line.substr(0,10).compare("#neighbors"))
919  {
920  std::string object_name;
921  std::string neighbors_list;
922 
923  std::getline(file_stream, object_name);
924  std::getline(file_stream, neighbors_list);
925 
926  string2Neighbors( object_name, neighbors_list);
927  }
928  }
929 
930  std::cout << "\nNEIGHTBORS:" << std::endl;
932 }
933 
934 void LoaderScene::string2Neighbors( const std::string & _name, const std::string & _neighbors)
935 {
936  if (_name.empty() || _neighbors.empty() || (!_neighbors.compare("NONE")))
937  return;
938 
939  // object name -> object color
940  glm::vec3 obj_col = name2Color(_name);
941  // disregard the background color
942  if (obj_col.r == this->backgr_col.r && obj_col.g == this->backgr_col.g && obj_col.b == this->backgr_col.b)
943  return;
944  // ADD THE COLOR AS MEMBER
945  neighb_rec_Ptr->addMember(obj_col);
946 
947  // neighbors -> object names -> object colors
948  // open a string stream
949  std::stringstream neighbors_ss(_neighbors);
950 
951  // split the string along the SPACE delimiter
952  std::string str_neighb;
953  while(std::getline(neighbors_ss,str_neighb,' '))
954  {
955  glm::vec3 neighb_col = name2Color(str_neighb);
956  // disregard the background color of the object color from above
957  if ((neighb_col.r == this->backgr_col.r && neighb_col.g == this->backgr_col.g && neighb_col.b == this->backgr_col.b) ||
958  (obj_col.r == neighb_col.r && obj_col.g == neighb_col.g && obj_col.b == neighb_col.b))
959  {
960  continue;
961  }
962  else
963  {
964  // ADD THE COLOR AS MEMBER
965  neighb_rec_Ptr->addMember(neighb_col);
966  // MARK THEM AS NEIGHBORS (repeats in the neighbor list are handled by NeighborhoodRecord)
967  neighb_rec_Ptr->addNeighbor(obj_col, neighb_col);
968  }
969 
970  }
971 
972 }
973 
974 glm::vec3 LoaderScene::name2Color( const std::string & _obj_name)
975 {
976  glm::vec3 obj_col = this->backgr_col;
977 
978  if (_obj_name.empty())
979  return obj_col;
980 
981  bool obj_name_found = false;
982  // look among the shell objects
983  for (unsigned int i = 0; i < counter_shell_obj; i++)
984  {
985  const char* tmp_name = shells[i]->getIdName();
986  if (!_obj_name.compare(tmp_name))
987  {
988  obj_col = shells[i]->getIdColor();
989  obj_name_found = true;
990  break;
991  }
992  }
993  // look among the contents
994  if (!obj_name_found)
995  {
996  for (unsigned int i = 0; i < counter_content_obj; i++)
997  {
998  const char* tmp_name = contents[i]->getIdName();
999  if (!_obj_name.compare(tmp_name))
1000  {
1001  obj_col = contents[i]->getIdColor();
1002  obj_name_found = true;
1003  break;
1004  }
1005  }
1006  }
1007  // look among the separators
1008  if (!obj_name_found)
1009  {
1010  for (unsigned int i = 0; i < counter_separator_obj; i++)
1011  {
1012  const char* tmp_name = separators[i]->getIdName();
1013  if (!_obj_name.compare(tmp_name))
1014  {
1015  obj_col = separators[i]->getIdColor();
1016  obj_name_found = true;
1017  break;
1018  }
1019  }
1020  }
1021 
1022  return obj_col;
1023 }
1024 
1025 
1027 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
1028 // %% --------------------------- SETUP RENDERING -------------------------- %% //
1029 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //
1031 
1033 {
1034 
1035  // initialize the projection matrix
1036  this->projectionMatrix = glm::perspective(60.0f,(float)screen_width/(float)screen_height, 0.1f,20.0f);
1037  this->projectionMatrix = glm::translate(this->projectionMatrix, glm::vec3(this->view_pos.x, this->view_pos.y, this->view_pos.z));
1038  // communicate to shaders using depth maps for logarithmic depth buffers
1043 
1044  // initialize the orthogonal matrix for post-preocessing
1045  this->orthoMatrix = glm::ortho(0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f);
1046 
1047  // initialize light positions
1048  this->light_pos_0 = this->light_pos_0_init;
1049  this->light_pos_1 = this->light_pos_1_init;
1050 
1051  // set the selected color to the screen background color
1052  this->selected_col = this->backgr_col;
1053 
1054  // post-processing setup
1055  FBOs_ready = true;
1056 
1057  // FBO for selecting objects (both color and depth for correct depth test - otherwise brightest col is always visible)
1058  fbo_0 = new vis2::FramebufferObject(screen_width, screen_height, false);
1060 
1061  // FBO setup EDGE DETECTION and FILTERING task (only color)
1062  FBOs_ready = setupEDF();
1063  if (!FBOs_ready)
1064  {
1065  std::cout << "Edge Detection and Filtering setup failed! No post-processing effects." << std::endl;
1066  return;
1067  }
1068 
1069  // FBO setup SELECTION MASKING and FILTERING task (only color)
1070  FBOs_ready = setupSMF();
1071  if (!FBOs_ready)
1072  {
1073  std::cout << "Selection Masking and Filtering setup failed! No post-processing effects." << std::endl;
1074  return;
1075  }
1076 
1077  // FBO setup DEPTH PEELING of SHELL task (both color and depth)
1078  FBOs_ready = setupDPS();
1079  if (!FBOs_ready)
1080  {
1081  std::cout << "Depth Peeling of Shell setup failed! No post-processing effects." << std::endl;
1082  return;
1083  }
1084 
1085  // FBO setup BLENDING of the result of DEPTH PEELING task (both color and depth)
1086  FBOs_ready = setupDPSB();
1087  if (!FBOs_ready)
1088  {
1089  std::cout << "Blending of the Depth Peeling setup failed! No post-processing effects." << std::endl;
1090  return;
1091  }
1092 
1093  // Quad for the final BLENDING
1095  quad_final_Ptr = new vis2::QuadTextured(glm::mat4(1.0f), shader_ctrls[VIS2_SHADER_TYPE_COMPLEX_BLEND], true);
1096  else
1097  FBOs_ready = false;
1098 
1099  // DEBUG quad (upper left quarter of viewport)
1101  quad_debug_Ptr = new vis2::QuadTextured(glm::mat4(1.0f), shader_ctrls[VIS2_SHADER_TYPE_BASIC_TEXTURED], false);
1102 
1103 }
1104 
1105 
1107 {
1108  // FBOs
1109  for (unsigned int i = 0; i < VIS2_SCENE_NR_FBOS_EDF; i++)
1110  {
1112  if (fbos_EDF[i]->getFBOStatus() != VIS2_FBO_SETUP_SUCCESS)
1113  return false;
1114  }
1115 
1116  // Shader controllers and quads
1117  if (!shaderEDFLoaded())
1118  {
1119  return false;
1120  }
1121  else
1122  {
1123  quads_EDF[0] = new vis2::QuadTextured(glm::mat4(1.0f), shader_ctrls[VIS2_SHADER_TYPE_EDGE_DETECT_H], true);
1124  quads_EDF[1] = new vis2::QuadTextured(glm::mat4(1.0f), shader_ctrls[VIS2_SHADER_TYPE_EDGE_DETECT_V], true);
1125 
1126  quads_EDF[2] = new vis2::QuadTextured(glm::mat4(1.0f), shader_ctrls[VIS2_SHADER_TYPE_BLUR_H], true);
1127  quads_EDF[3] = new vis2::QuadTextured(glm::mat4(1.0f), shader_ctrls[VIS2_SHADER_TYPE_BLUR_V], true);
1128  }
1129 
1130  return true;
1131 }
1132 
1134 {
1135  // FBOs
1136  for (unsigned int i = 0; i < VIS2_SCENE_NR_FBOS_SMF; i++)
1137  {
1139  if (fbos_SMF[i]->getFBOStatus() != VIS2_FBO_SETUP_SUCCESS)
1140  return false;
1141  }
1142 
1143  // Shader controllers and quads
1144  if (!shaderSMFLoaded())
1145  {
1146  return false;
1147  }
1148  else
1149  {
1150  quads_SMF[0] = new vis2::QuadTextured(glm::mat4(1.0f), shader_ctrls[VIS2_SHADER_TYPE_MASK], true);
1151  quads_SMF[1] = new vis2::QuadTextured(glm::mat4(1.0f), shader_ctrls[VIS2_SHADER_TYPE_BLUR_H], true);
1152  quads_SMF[2] = new vis2::QuadTextured(glm::mat4(1.0f), shader_ctrls[VIS2_SHADER_TYPE_BLUR_V], true);
1153  }
1154 
1155  return true;
1156 }
1157 
1159 {
1160  // FBOs
1161  for (unsigned int i = 0; i < VIS2_SCENE_NR_FBOS_DPS; i++)
1162  {
1164  if (fbos_DPS[i]->getFBOStatus() != VIS2_FBO_SETUP_SUCCESS)
1165  return false;
1166  }
1167 
1168  // Shader controllers (no quads necessary -> renders only geometry)
1169  if (!shaderDPSLoaded())
1170  return false;
1171 
1172  return true;
1173 }
1174 
1176 {
1177  // FBOs
1178  for (unsigned int i = 0; i < VIS2_SCENE_NR_FBOS_DPSB; i++)
1179  {
1181  if (fbos_DPSB[i]->getFBOStatus() != VIS2_FBO_SETUP_SUCCESS)
1182  return false;
1183  }
1184 
1185  // Shader controllers (no quads necessary -> renders only geometry)
1186  if (!shaderDPSBLoaded())
1187  {
1188  return false;
1189  }
1190  else
1192 
1193  return true;
1194 }
1195 
1196 
1197 glm::vec3 LoaderScene::getSelectedColorId(glm::vec3 & _color_in, float _tolerance)
1198 {
1199 
1200  glm::vec3 found_col = this->backgr_col;
1201 
1202  bool found = false;
1203  for (unsigned int i = 0; i < counter_content_obj; i++)
1204  {
1205  if (contents_loaded[i])
1206  {
1207  glm::vec3 tmp_col = contents[i]->getIdColor();
1208  found = (abs(tmp_col.r - _color_in.r) < _tolerance) &&
1209  (abs(tmp_col.g - _color_in.g) < _tolerance) &&
1210  (abs(tmp_col.b - _color_in.b) < _tolerance);
1211  if (found)
1212  {
1213  found_col = tmp_col;
1214  break;
1215  }
1216  }
1217  }
1218 
1219  return found_col;
1220 }