Direct Graphical Models  v.1.7.0
MarkerGraph.cpp
1 #include "MarkerGraph.h"
2 #include "DGM/IGraphPairwise.h"
3 #include "ColorSpaces.h"
4 #include "macroses.h"
5 
6 #ifdef USE_OPENGL
7 #include "GL/glew.h"
8 #include "GLFW/glfw3.h"
9 #include "glm/glm.hpp"
10 #include "glm/gtc/matrix_transform.hpp"
11 
12 #include "CameraControl.h"
13 #endif
14 
15 namespace DirectGraphicalModels { namespace vis
16 {
17  // Constants
18  const byte bkgIntencity = 50;
19 
20  namespace {
21  // Draws line with interpolated color
22  void drawLine(Mat &img, Point pt1, Point pt2, Scalar color1, Scalar color2, int thikness = 1, int lineType = LINE_8, int shift = 0)
23  {
24  const int nSegments = 8;
25 
26  Point2f Pt1 = static_cast<Point2f>(pt1);
27  Point2f inc = static_cast<Point2f>(pt2 - pt1) / nSegments;
28  for (int i = 0; i < nSegments; i++) {
29  Point2f Pt2 = Pt1 + inc;
30  double a = static_cast<double>(i) / nSegments;
31  Scalar color = (1 - a) * color1 + a * color2;
32  line(img, Pt1, Pt2, color, thikness, lineType, shift);
33  Pt1 = Pt2;
34  }
35  }
36 
37  // Draws filled triangle
38  void drawTriangle(Mat &img, Point pt1, Point pt2, Point pt3, Scalar color, int lineType = LINE_8, int shift = 0)
39  {
40  Point triangle[1][3] = {{ pt1, pt2, pt3 }};
41  const Point * pts[1] = { triangle[0] };
42  int npts = 3;
43  fillPoly(img, pts, &npts, 1, color, lineType, shift);
44  }
45 
46  // Draws an arrow
47  void drawArrow(Mat &img, Point pt1, Point pt2, Scalar color, int lineType = LINE_8, int shift = 0, double tipLength = 15)
48  {
49  Point2f dir = static_cast<Point2f>(pt1 - pt2);
50  float len = sqrtf(dir.dot(dir));
51  dir *= tipLength / len;
52 
53  float alpha = 15 * static_cast<float>(Pi) / 180;
54  float cs = cosf(alpha);
55  float sn = sinf(alpha);
56 
57  Point2f left( dir.dot(Point2f(cs, -sn)) + 0.5f, dir.dot(Point2f( sn, cs)) + 0.5f);
58  Point2f right(dir.dot(Point2f(cs, sn)) + 0.5f, dir.dot(Point2f(-sn, cs)) + 0.5f);
59 
60  drawTriangle(img, pt2, pt2 + static_cast<Point>(left), pt2 + static_cast<Point>(right), color, lineType, shift);
61  }
62 
63 // void drawArrowedLine(Mat &img, Point pt1, Point pt2, Scalar color, int thikness = 1, int lineType = LINE_8, int shift = 0, double tipLength = 15)
64 // {
65 // line(img, pt1, pt2, color, thikness, lineType, shift);
66 // drawArrow(img, pt1, pt2, color, lineType, shift, tipLength);
67 // }
68 
69  void drawArrowedLine(Mat &img, Point pt1, Point pt2, Scalar color1, Scalar color2, int thikness = 1, int lineType = LINE_8, int shift = 0, double tipLength = 15)
70  {
71  drawLine(img, pt1, pt2, color1, color2, thikness, lineType, shift);
72  drawArrow(img, pt1, pt2, color2, lineType, shift, tipLength);
73  }
74  }
75 
76  Mat drawGraph(int size, IGraphPairwise &graph, std::function<Point2f(size_t)> posFunc, std::function<cv::Scalar(size_t)> colorFunc, const vec_scalar_t &groupsColor)
77  {
78  Point2f pt1, pt2;
79  Scalar color1, color2;
80 
81  const size_t nNodes = graph.getNumNodes();
82 
83  Mat res(size, size, CV_8UC3);
84  Mat alpha(size, size, CV_8UC3);
85  res.setTo(bkgIntencity);
86 
87  // Edges
88  for (size_t n = 0; n < nNodes; n++) {
89  vec_size_t childs;
90  graph.getChildNodes(n, childs);
91 
92  pt1 = posFunc(n);
93  pt1.x = 0.5f * (1 + pt1.x) * size;
94  pt1.y = 0.5f * (1 + pt1.y) * size;
95 
96  color1 = colorFunc ? colorFunc(n) : colorspaces::hsv2rgb(DGM_HSV(360.0 * n / nNodes, 255.0, 192.0));
97 
98  for (size_t c : childs) {
99  if (graph.isEdgeArc(n, c) && n < c) continue; // draw only one edge in arc
100 
101  pt2 = posFunc(c);
102  pt2.x = 0.5f * (1 + pt2.x) * size;
103  pt2.y = 0.5f * (1 + pt2.y) * size;
104  color2 = colorFunc ? colorFunc(c) : colorspaces::hsv2rgb(DGM_HSV(360.0 * c / nNodes, 255.0, 192.0));
105 
106  // Group edge color
107  if (groupsColor.size() > 0)
108  color1 = color2 = groupsColor[graph.getEdgeGroup(n, c) % groupsColor.size()];
109 
110  alpha.setTo(0);
111  if (graph.isEdgeArc(n, c)) drawLine(alpha, pt1, pt2, color1, color2, 1, cv::LineTypes::LINE_AA);
112  else drawArrowedLine(alpha, pt1, pt2, color1, color2, 1, cv::LineTypes::LINE_AA);
113  add(res, alpha, res);
114  }
115  }
116 
117  // Nodes
118  for (size_t n = 0; n < nNodes; n++) {
119  color1 = colorFunc ? colorFunc(n) : colorspaces::hsv2rgb(DGM_HSV(360.0 * n / nNodes, 255.0, 255.0));
120  pt1 = posFunc(n);
121  pt1.x = 0.5f * (1 + pt1.x) * size;
122  pt1.y = 0.5f * (1 + pt1.y) * size;
123  circle(res, pt1, 3, color1, -1, cv::LineTypes::LINE_AA);
124  } // n
125 
126  return res;
127  }
128 
129 #ifdef USE_OPENGL
130  // types
131  using vec_vec3_t = std::vector<glm::vec3>;
132 
133  namespace {
134  void LoadShaders(GLuint &NodeProgramID, GLuint &EdgeProgramID)
135  {
136 #ifdef DEBUG_MODE
137  GLint Result = GL_FALSE;
138  int InfoLogLength = 0;
139 #endif
140  // -------------- Vertex Shader --------------
141  GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
142  {
143  const std::string sourceCode =
144 #include "VertexShader.glsl"
145  ;
146 #ifdef DEBUG_PRINT_INFO
147  printf("Compiling vertex shader... ");
148 #endif
149  char const * VertexSourcePointer = sourceCode.c_str();
150  glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
151  glCompileShader(VertexShaderID);
152 
153 #ifdef DEBUG_MODE // Check Vertex Shader
154  glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
155  glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
156  if (InfoLogLength > 1) {
157  std::vector<char> VertexShaderErrorMessage(InfoLogLength + 1);
158  glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
159  printf("\n%s\n", &VertexShaderErrorMessage[0]);
160  }
161 #endif
162 #ifdef DEBUG_PRINT_INFO
163  printf("Done\n");
164 #endif
165  }
166 
167  // -------------- Node Fragment Shader --------------
168  GLuint NodeFragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
169  {
170  const std::string sourceCode =
171 #include "NodeFragmentShader.glsl"
172  ;
173 #ifdef DEBUG_PRINT_INFO
174  printf("Compiling node fragment Shader... ");
175 #endif
176  char const * FragmentSourcePointer = sourceCode.c_str();
177  glShaderSource(NodeFragmentShaderID, 1, &FragmentSourcePointer, NULL);
178  glCompileShader(NodeFragmentShaderID);
179 
180 #ifdef DEBUG_MODE // Check Fragment Shader
181  glGetShaderiv(NodeFragmentShaderID, GL_COMPILE_STATUS, &Result);
182  glGetShaderiv(NodeFragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
183  if (InfoLogLength > 1) {
184  std::vector<char> FragmentShaderErrorMessage(InfoLogLength + 1);
185  glGetShaderInfoLog(NodeFragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
186  printf("\n%s\n", &FragmentShaderErrorMessage[0]);
187  }
188 #endif
189 #ifdef DEBUG_PRINT_INFO
190  printf("Done\n");
191 #endif
192  }
193 
194  // -------------- Edge Fragment Shader --------------
195  GLuint EdgeFragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
196  {
197  const std::string sourceCode =
198 #include "EdgeFragmentShader.glsl"
199  ;
200 #ifdef DEBUG_PRINT_INFO
201  printf("Compiling edge fragment shader... ");
202 #endif
203  char const * FragmentSourcePointer = sourceCode.c_str();
204  glShaderSource(EdgeFragmentShaderID, 1, &FragmentSourcePointer, NULL);
205  glCompileShader(EdgeFragmentShaderID);
206 
207 #ifdef DEBUG_MODE // Check Fragment Shader
208  glGetShaderiv(EdgeFragmentShaderID, GL_COMPILE_STATUS, &Result);
209  glGetShaderiv(EdgeFragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
210  if (InfoLogLength > 1) {
211  std::vector<char> FragmentShaderErrorMessage(InfoLogLength + 1);
212  glGetShaderInfoLog(EdgeFragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
213  printf("\n%s\n", &FragmentShaderErrorMessage[0]);
214  }
215 #endif
216 #ifdef DEBUG_PRINT_INFO
217  printf("Done\n");
218 #endif
219  }
220 
221 
222  // -------------- Node Program --------------
223  {
224 #ifdef DEBUG_PRINT_INFO
225  printf("Linking node program... ");
226 #endif
227  NodeProgramID = glCreateProgram();
228  glAttachShader(NodeProgramID, VertexShaderID);
229  glAttachShader(NodeProgramID, NodeFragmentShaderID);
230  glLinkProgram(NodeProgramID);
231 
232 #ifdef DEBUG_MODE // Check the program
233  glGetProgramiv(NodeProgramID, GL_LINK_STATUS, &Result);
234  glGetProgramiv(NodeProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
235  if (InfoLogLength > 1) {
236  std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
237  glGetProgramInfoLog(NodeProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
238  printf("%s\n", &ProgramErrorMessage[0]);
239  }
240 #endif
241 #ifdef DEBUG_PRINT_INFO
242  printf("Done\n");
243 #endif
244  glDetachShader(NodeProgramID, VertexShaderID);
245  glDetachShader(NodeProgramID, NodeFragmentShaderID);
246  }
247 
248  // -------------- Edge Program --------------
249  {
250 #ifdef DEBUG_PRINT_INFO
251  printf("Linking edge program... ");
252 #endif
253  EdgeProgramID = glCreateProgram();
254  glAttachShader(EdgeProgramID, VertexShaderID);
255  glAttachShader(EdgeProgramID, EdgeFragmentShaderID);
256  glLinkProgram(EdgeProgramID);
257 
258 #ifdef DEBUG_MODE // Check the program
259  glGetProgramiv(EdgeProgramID, GL_LINK_STATUS, &Result);
260  glGetProgramiv(EdgeProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
261  if (InfoLogLength > 1) {
262  std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
263  glGetProgramInfoLog(EdgeProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
264  printf("%s\n", &ProgramErrorMessage[0]);
265  }
266 #endif
267 #ifdef DEBUG_PRINT_INFO
268  printf("Done\n");
269 #endif
270  glDetachShader(NodeProgramID, VertexShaderID);
271  glDetachShader(NodeProgramID, NodeFragmentShaderID);
272  }
273 
274  glDeleteShader(VertexShaderID);
275  glDeleteShader(NodeFragmentShaderID);
276  glDeleteShader(EdgeFragmentShaderID);
277  }
278 
279  void addCone(vec_vec3_t &vVertices, vec_vec3_t &vColors, vec_word_t &vIndices, glm::vec3 pt1, glm::vec3 pt2, glm::vec3 color, float length)
280  {
281  const int nSectors = 32;
282 
283  word v0 = static_cast<word>(vVertices.size());
284 
285  glm::vec3 dir = glm::normalize(pt1 - pt2); // cone's axis
286  glm::vec3 normal = glm::cross(dir, glm::vec3(0, 0, 1)); // normal to cone's axis
287  if (glm::length(normal) < FLT_EPSILON) normal = glm::cross(dir, glm::vec3(0, 1, 0));
288  normal = glm::normalize(normal);
289  glm::vec3 top = pt2; // cone's top point
290  glm::vec3 mid = pt2 + dir * length; // cone's middle point
291 
292  glm::mat4 rmat = glm::rotate(glm::mat4(1), glm::radians(360.0f / nSectors), dir);
293 
294  glm::vec3 point1 = normal * length * glm::tan(glm::radians(15.0f));
295  for (unsigned short i = 0; i < nSectors; i++) {
296  glm::vec3 point2 = rmat * glm::vec4(point1, 1.0f);
297  vVertices.push_back(mid + point1);
298  vColors.push_back(color);
299  point1 = point2;
300  }
301 
302  vVertices.push_back(top);
303  vColors.push_back(color);
304 
305  vVertices.push_back(mid);
306  vColors.push_back(color);
307 
308  for (word i = 1; i <= nSectors; i++) {
309  // Side triangle
310  vIndices.push_back(v0 + i - 1);
311  vIndices.push_back(v0 + i % nSectors);
312  vIndices.push_back(v0 + nSectors);
313 
314  // Base triangle
315  vIndices.push_back(v0 + i % nSectors);
316  vIndices.push_back(v0 + i - 1);
317  vIndices.push_back(v0 + nSectors + 1);
318  }
319  }
320  }
321 
322  void showGraph3D(int size, IGraphPairwise &graph, std::function<Point3f(size_t)> posFunc, std::function<cv::Scalar(size_t)> colorFunc, const vec_scalar_t &groupsColor)
323  {
324  // Constants
325  const size_t nNodes = graph.getNumNodes();
326  const bool isGroupsColor = groupsColor.size() > 0;
327 
328  // Initialise GLFW
329  DGM_ASSERT_MSG(glfwInit(), "Failed to initialize GLFW");
330 
331  // Window creation hints
332  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Tell GLFW to use OpenGL 3.3
333  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
334  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
335  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
336  glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Disable window resizing
337  glfwWindowHint(GLFW_SAMPLES, 16);
338 
339  // Create a windowed mode window and its OpenGL context
340  GLFWwindow *window = glfwCreateWindow(size, size, "3D Graph Viewer", NULL, NULL);
341  if (!window) {
342  DGM_WARNING("Unable to create GLFW window");
343  glfwTerminate();
344  return;
345  }
346 
347  glfwMakeContextCurrent(window); // Make the window's context current
348  glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); // Ensure we can capture the escape key being pressed below
349 
350  // Initialize GLEW
351  DGM_ASSERT_MSG(glewInit() == GLEW_OK, "Failed to initialize GLEW");
352 
353 #ifdef DEBUG_PRINT_INFO
354  printf("OpenGL Ver: %s\n", glGetString(GL_VERSION));
355 #endif
356 
357  // Options
358  glShadeModel(GL_SMOOTH); // Select flat or smooth shading
359  //glEnable(GL_DEPTH_TEST); // Ebable depth buffer
360  //glDepthFunc(GL_LESS); // Specify the value used for depth buffer comparisons
361  glEnable(GL_PROGRAM_POINT_SIZE);
362  glEnable(GL_BLEND); // Enable blending
363  //glBlendFunc(GL_SRC_ALPHA, GL_ONE);
364  glFrontFace(GL_CW); // Define front- and back-facing polygons
365  glEnable(GL_CULL_FACE);
366  //glCullFace(GL_BACK);
367 
368  GLuint vertex_array_id;
369  glGenVertexArrays(1, &vertex_array_id);
370  glBindVertexArray(vertex_array_id);
371 
372  // Create and compile our GLSL program from the shaders
373  GLuint NodeProgramID, EdgeProgramID; // Different shaders for graph nodes and edges
374  LoadShaders(NodeProgramID, EdgeProgramID);
375 
376  // Get a handle for our "MVP" uniform
377  GLuint NodeMatrixID = glGetUniformLocation(NodeProgramID, "MVP");
378  GLuint EdgeMatrixID = glGetUniformLocation(EdgeProgramID, "MVP");
379 
380  // Main containers
381  vec_vec3_t vVertices;
382  vec_vec3_t vColors;
383  vec_vec3_t vGroupColors;
384  vec_word_t vIndices, vConeIndices;
385 
386  // Filling in the containers
387  // Nodes
388  for (size_t n = 0; n < nNodes; n++) {
389  Point3f pt = posFunc(n);
390  vVertices.push_back(glm::vec3(pt.x, pt.y, pt.z));
391  cv::Scalar color = colorFunc ? colorspaces::bgr2rgb(colorFunc(n)) : colorspaces::hsv2bgr(DGM_HSV(360.0 * n / nNodes, 255.0, 255.0));
392  color = static_cast<Scalar>(color) / 255;
393  vColors.push_back(glm::vec3(color.val[0], color.val[1], color.val[2]));
394  }
395 
396  // Edges
397  for (size_t n = 0; n < nNodes; n++) {
398  vec_size_t childs;
399  graph.getChildNodes(n, childs);
400 
401  for (size_t c : childs) {
402  if (graph.isEdgeArc(n, c) && n < c) continue; // draw only one edge in arc
403  vIndices.push_back(static_cast<word>(n)); // src
404  vIndices.push_back(static_cast<word>(c)); // dst
405 
406  if (isGroupsColor) {
407  byte group = graph.getEdgeGroup(n, c);
408  cv::Scalar color = groupsColor[group % groupsColor.size()];
409  color = static_cast<Scalar>(color) / 255;
410  vGroupColors.push_back(glm::vec3(color.val[0], color.val[1], color.val[2]));
411  }
412 
413  if (!graph.isEdgeArc(n, c))
414  addCone(vVertices, vColors, vConeIndices, vVertices[n], vVertices[c], vColors[c], 30.0f / size);
415  }
416  }
417  const size_t nEdgesIdx = vIndices.size(); // Number of edge indices in the container
418  vIndices.insert(vIndices.end(), vConeIndices.begin(), vConeIndices.end());
419  vConeIndices.clear();
420 
421  // Binding the containers: xxxBuffer to vXXX
422  GLuint vertexBuffer;
423  glGenBuffers(1, &vertexBuffer); // Create 1 buffer
424  glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); // Make this buffer current
425  glBufferData(GL_ARRAY_BUFFER, vVertices.size() * sizeof(glm::vec3), &vVertices[0], GL_STATIC_DRAW); // transmit data
426 
427  GLuint colorBuffer;
428  glGenBuffers(1, &colorBuffer);
429  glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
430  glBufferData(GL_ARRAY_BUFFER, vColors.size() * sizeof(glm::vec3), &vColors[0], GL_STATIC_DRAW);
431 
432  GLuint groupColorBuffer;
433  if (isGroupsColor) {
434  glGenBuffers(1, &groupColorBuffer);
435  glBindBuffer(GL_ARRAY_BUFFER, groupColorBuffer);
436  glBufferData(GL_ARRAY_BUFFER, vGroupColors.size() * sizeof(glm::vec3), &vGroupColors[0], GL_STATIC_DRAW);
437  }
438 
439  GLuint indexBuffer;
440  glGenBuffers(1, &indexBuffer);
441  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
442  glBufferData(GL_ELEMENT_ARRAY_BUFFER, vIndices.size() * sizeof(word), &vIndices[0], GL_STATIC_DRAW);
443 
444  CCameraControl camera(window);
445 
446  const float _bkgIntencity = static_cast<float>(bkgIntencity) / 255;
447  glClearColor(_bkgIntencity, _bkgIntencity, _bkgIntencity, 0.0f); // Set background color
448 
449  glm::mat4 ModelMatrix = glm::mat4(1.0f);
450  //glm::mat4 ViewMatrix = glm::lookAt(glm::vec3(0.0f, 0.0f, 5.0f), glm::vec3(0., 0., 0.), glm::vec3(0., 1., 0.));
451  glm::mat4 ProjectionMatrix = glm::perspective(glm::radians(45.0f), 1.0f, 0.1f, 100.0f);
452 
453  // Main loop
454  while (!glfwWindowShouldClose(window) && glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS ) {
455  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear information from last draw
456 
457  // Compute the MVP matrix from keyboard and mouse input
458  if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) camera.reset();
459  glm::mat4 MVP = ProjectionMatrix * camera.getViewMatrix() * ModelMatrix;
460 
461  // 1-st attribute buffer : vertices
462  glEnableVertexAttribArray(0);
463  glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
464  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
465 
466  // 2-nd attribute buffer : colors
467  glEnableVertexAttribArray(1);
468  glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
469  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
470 
471  // 3-rd attribute buffer : group-colors
472  if (isGroupsColor) {
473  glEnableVertexAttribArray(1);
474  glBindBuffer(GL_ARRAY_BUFFER, groupColorBuffer);
475  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
476  }
477 
478  if (true) { // Draw nodes
479  glUseProgram(NodeProgramID);
480 
481  // Send our transformation to the currently bound shader, in the "MVP" uniform
482  glUniformMatrix4fv(NodeMatrixID, 1, GL_FALSE, &MVP[0][0]);
483 
484  glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(nNodes));
485  }
486 
487  if (true) { // Draw edges
488  glUseProgram(EdgeProgramID);
489 
490  glUniformMatrix4fv(EdgeMatrixID, 1, GL_FALSE, &MVP[0][0]); // Send our transformation to the currently bound shader, in the "MVP" uniform
491 
492  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); // Index buffer
493 
494  glDrawElements(GL_LINES, static_cast<GLsizei>(nEdgesIdx), GL_UNSIGNED_SHORT, (void *) 0); // Edges
495  glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(vIndices.size() - nEdgesIdx), GL_UNSIGNED_SHORT, (void *) (nEdgesIdx * sizeof(word))); // Cones
496  }
497 
498  glDisableVertexAttribArray(0);
499  glDisableVertexAttribArray(1);
500 
501  glfwSwapBuffers(window); // Swap front and back buffers
502  glfwPollEvents(); // Poll for and process events
503  }
504 
505  // Cleanup VBO and shader
506  glDeleteBuffers(1, &vertexBuffer);
507  glDeleteBuffers(1, &colorBuffer);
508  if (isGroupsColor) glDeleteBuffers(1, &groupColorBuffer);
509  glDeleteBuffers(1, &indexBuffer);
510 
511  glDeleteProgram(NodeProgramID);
512  glDeleteProgram(EdgeProgramID);
513  glDeleteVertexArrays(1, &vertex_array_id);
514 
515  // Close OpenGL window and terminate GLFW
516  glfwTerminate();
517  }
518 #endif
519 } }
std::vector< glm::vec3 > vec_vec3_t
virtual void getChildNodes(size_t node, vec_size_t &vNodes) const =0
Returns the set of IDs of the child nodes of the argument node.
Trackball camera control class.
Definition: CameraControl.h:16
virtual size_t getNumNodes(void) const =0
Returns the number of nodes in the graph.
cv::Scalar bgr2rgb(cv::Scalar bgr)
Transforms color from RGB to BGR.
Definition: ColorSpaces.h:37
Mat drawGraph(int size, IGraphPairwise &graph, std::function< Point2f(size_t)> posFunc, std::function< cv::Scalar(size_t)> colorFunc, const vec_scalar_t &groupsColor)
Visualizes the graph structure.
Definition: MarkerGraph.cpp:76
glm::mat4 getViewMatrix(void)
Returns the view matrix within the camera coordinate.
virtual byte getEdgeGroup(size_t srcNode, size_t dstNode) const =0
Returns the group of the edge.
cv::Scalar hsv2rgb(cv::Scalar hsv)
Transforms color from HSV to RGB space.
Definition: ColorSpaces.h:107
void reset(void)
Resets the camera position.
Interface class for graphical models.
void showGraph3D(int size, IGraphPairwise &graph, std::function< Point3f(size_t)> posFunc, std::function< cv::Scalar(size_t)> colorFunc, const vec_scalar_t &groupsColor)
Visualizes the graph structure in 3D.
cv::Scalar hsv2bgr(cv::Scalar hsv)
Transforms color from HSV to BGR space.
Definition: ColorSpaces.h:44
virtual bool isEdgeArc(size_t srcNode, size_t dstNode) const
Checks whether the edge is a part of an arc.