1 // Copyright (c) 2018  GeometryFactory Sarl (France).
2 // All rights reserved.
3 //
4 // This file is part of CGAL (www.cgal.org).
5 //
6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h $
7 // $Id: Basic_viewer_qt.h fb6f703 2021-05-04T14:07:49+02:00 Sébastien Loriot
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 //
11 // Author(s)     : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
12 
13 #ifndef CGAL_BASIC_VIEWER_QT_H
14 #define CGAL_BASIC_VIEWER_QT_H
15 
16 #include <CGAL/license/GraphicsView.h>
17 #include <iostream>
18 #include <tuple>
19 #include <string>
20 
21 #ifdef CGAL_USE_BASIC_VIEWER
22 
23 #ifdef __GNUC__
24 #if  __GNUC__ >= 9
25 #  pragma GCC diagnostic push
26 #  pragma GCC diagnostic ignored "-Wdeprecated-copy"
27 #endif
28 #endif
29 
30 #include <QApplication>
31 #include <QKeyEvent>
32 
33 #include <CGAL/Qt/qglviewer.h>
34 #include <CGAL/Qt/manipulatedFrame.h>
35 #include <QKeyEvent>
36 #include <QOpenGLVertexArrayObject>
37 #include <QGLBuffer>
38 #include <QOpenGLShaderProgram>
39 
40 #ifdef __GNUC__
41 #if __GNUC__ >= 9
42 #  pragma GCC diagnostic pop
43 #endif
44 #endif
45 
46 #include <vector>
47 #include <cstdlib>
48 #include <cfloat>
49 
50 #include <CGAL/Buffer_for_vao.h>
51 #include <CGAL/Basic_shaders.h>
52 #include <CGAL/Qt/CreateOpenGLContext.h>
53 #include <CGAL/Qt/constraint.h>
54 #include <CGAL/Random.h>
55 
56 namespace CGAL
57 {
58 //------------------------------------------------------------------------------
get_random_color(CGAL::Random & random)59 inline CGAL::IO::Color get_random_color(CGAL::Random& random)
60 {
61   CGAL::IO::Color res;
62   do
63   {
64     res=CGAL::IO::Color(random.get_int(0,256),
65                     random.get_int(0,256),
66                     random.get_int(0,256));
67   }
68   while(res.red()==255 && res.green()==255 && res.blue()==255);
69   return res;
70 }
71 //------------------------------------------------------------------------------
72 class Basic_viewer_qt : public CGAL::QGLViewer
73 {
74 public:
75   typedef CGAL::Exact_predicates_inexact_constructions_kernel Local_kernel;
76   typedef Local_kernel::Point_3  Local_point;
77   typedef Local_kernel::Vector_3 Local_vector;
78 
79   // Constructor/Destructor
80   Basic_viewer_qt(QWidget* parent,
81                   const char* title="",
82                   bool draw_vertices=false,
83                   bool draw_edges=true,
84                   bool draw_faces=true,
85                   bool use_mono_color=false,
86                   bool inverse_normal=false,
87                   bool draw_rays=true,
88                   bool draw_lines=true,
89                   bool draw_text=true,
90                   bool no_2D_mode=false) :
QGLViewer(parent)91     CGAL::QGLViewer(parent),
92     m_draw_vertices(draw_vertices),
93     m_draw_edges(draw_edges),
94     m_draw_rays(draw_rays),
95     m_draw_lines(draw_lines),
96     m_draw_faces(draw_faces),
97     m_flatShading(true),
98     m_use_mono_color(use_mono_color),
99     m_inverse_normal(inverse_normal),
100     m_draw_text(draw_text),
101     m_no_2D_mode(no_2D_mode),
102     m_size_points(7.),
103     m_size_edges(3.1),
104     m_size_rays(3.1),
105     m_size_lines(3.1),
106     m_vertices_mono_color(200, 60, 60),
107     m_edges_mono_color(0, 0, 0),
108     m_rays_mono_color(0, 0, 0),
109     m_lines_mono_color(0, 0, 0),
110     m_faces_mono_color(60, 60, 200),
111     m_ambient_color(0.6f, 0.5f, 0.5f, 0.5f),
112     m_are_buffers_initialized(false),
113     m_buffer_for_mono_points(&arrays[POS_MONO_POINTS],
114                              nullptr,
115                              &m_bounding_box,
116                              nullptr, nullptr, nullptr),
117     m_buffer_for_colored_points(&arrays[POS_COLORED_POINTS],
118                                 nullptr,
119                                 &m_bounding_box,
120                                 &arrays[COLOR_POINTS],
121                                 nullptr, nullptr),
122     m_buffer_for_mono_segments(&arrays[POS_MONO_SEGMENTS],
123                                nullptr,
124                                &m_bounding_box,
125                                nullptr, nullptr, nullptr),
126     m_buffer_for_colored_segments(&arrays[POS_COLORED_SEGMENTS],
127                                   nullptr,
128                                   &m_bounding_box,
129                                   &arrays[COLOR_SEGMENTS],
130                                   nullptr, nullptr),
131     m_buffer_for_mono_rays(&arrays[POS_MONO_RAYS],
132                             nullptr,
133                             &m_bounding_box,
134                             nullptr, nullptr),
135     m_buffer_for_colored_rays(&arrays[POS_COLORED_RAYS],
136                                nullptr,
137                                &m_bounding_box,
138                                &arrays[COLOR_RAYS],
139                                nullptr, nullptr),
140     m_buffer_for_mono_lines(&arrays[POS_MONO_RAYS],
141                            nullptr,
142                            &m_bounding_box,
143                            nullptr, nullptr),
144     m_buffer_for_colored_lines(&arrays[POS_COLORED_LINES],
145                               nullptr,
146                               &m_bounding_box,
147                               &arrays[COLOR_LINES],
148                               nullptr, nullptr),
149     m_buffer_for_mono_faces(&arrays[POS_MONO_FACES],
150                             nullptr,
151                             &m_bounding_box,
152                             nullptr,
153                             &arrays[FLAT_NORMAL_MONO_FACES],
154                             &arrays[SMOOTH_NORMAL_MONO_FACES]),
155     m_buffer_for_colored_faces(&arrays[POS_COLORED_FACES],
156                                nullptr,
157                                &m_bounding_box,
158                                &arrays[COLOR_FACES],
159                                &arrays[FLAT_NORMAL_COLORED_FACES],
160                                &arrays[SMOOTH_NORMAL_COLORED_FACES])
161   {
162     // Define 'Control+Q' as the new exit shortcut (default was 'Escape')
163     setShortcut(qglviewer::EXIT_VIEWER, ::Qt::CTRL+::Qt::Key_Q);
164 
165     // Add custom key description (see keyPressEvent).
166     setKeyDescription(::Qt::Key_C, "Switch clipping plane display mode");
167     setKeyDescription(::Qt::Key_C+::Qt::AltModifier, "Toggle clipping plane rendering on/off");
168     setKeyDescription(::Qt::Key_E, "Toggles edges display");
169     setKeyDescription(::Qt::Key_M, "Toggles mono color");
170     setKeyDescription(::Qt::Key_N, "Inverse direction of normals");
171     setKeyDescription(::Qt::Key_S, "Switch between flat/Gouraud shading display");
172     setKeyDescription(::Qt::Key_T, "Toggles text display");
173     setKeyDescription(::Qt::Key_U, "Move camera direction upside down");
174     setKeyDescription(::Qt::Key_V, "Toggles vertices display");
175     setKeyDescription(::Qt::Key_W, "Toggles faces display");
176     setKeyDescription(::Qt::Key_Plus, "Increase size of edges");
177     setKeyDescription(::Qt::Key_Minus, "Decrease size of edges");
178     setKeyDescription(::Qt::Key_Plus+::Qt::ControlModifier, "Increase size of vertices");
179     setKeyDescription(::Qt::Key_Minus+::Qt::ControlModifier, "Decrease size of vertices");
180     setKeyDescription(::Qt::Key_PageDown, "Increase light (all colors, use shift/alt/ctrl for one rgb component)");
181     setKeyDescription(::Qt::Key_PageUp, "Decrease light (all colors, use shift/alt/ctrl for one rgb component)");
182     setKeyDescription(::Qt::Key_O, "Toggles 2D mode only");
183 
184     // Add custom mouse description
185     setMouseBindingDescription(::Qt::Key_C, ::Qt::ControlModifier, ::Qt::LeftButton, "Rotate the clipping plane when enabled");
186     setMouseBindingDescription(::Qt::Key_C, ::Qt::ControlModifier, ::Qt::RightButton, "Translate the clipping plane when enabled");
187     setMouseBindingDescription(::Qt::Key_C, ::Qt::ControlModifier, ::Qt::MiddleButton, "Control the clipping plane transparency when enabled");
188 
189     setMouseBinding(::Qt::ControlModifier, ::Qt::LeftButton, qglviewer::FRAME, qglviewer::NO_MOUSE_ACTION);
190     setMouseBinding(::Qt::ControlModifier, ::Qt::RightButton, qglviewer::FRAME, qglviewer::NO_MOUSE_ACTION);
191     setMouseBinding(::Qt::ControlModifier, ::Qt::MiddleButton, qglviewer::FRAME, qglviewer::NO_MOUSE_ACTION);
192     setWheelBinding(::Qt::ControlModifier, qglviewer::FRAME, qglviewer::NO_MOUSE_ACTION);
193 
194     setMouseBinding(::Qt::Key_C, ::Qt::ControlModifier, ::Qt::LeftButton, qglviewer::FRAME, qglviewer::ROTATE);
195     setMouseBinding(::Qt::Key_C, ::Qt::ControlModifier, ::Qt::RightButton, qglviewer::FRAME, qglviewer::TRANSLATE);
196     setMouseBinding(::Qt::Key_C, ::Qt::ControlModifier, ::Qt::MiddleButton, qglviewer::FRAME, qglviewer::ZOOM);
197     setWheelBinding(::Qt::Key_C, ::Qt::ControlModifier, qglviewer::FRAME, qglviewer::ZOOM);
198 
199     if (title[0]==0)
200       setWindowTitle("CGAL Basic Viewer");
201     else
202       setWindowTitle(title);
203 
204     resize(500, 450);
205 
206     if (inverse_normal)
207     { negate_all_normals(); }
208   }
209 
~Basic_viewer_qt()210   ~Basic_viewer_qt()
211   {
212     makeCurrent();
213     for (unsigned int i=0; i<NB_VBO_BUFFERS; ++i)
214       buffers[i].destroy();
215 
216     for (unsigned int i=0; i<NB_VAO_BUFFERS; ++i)
217       vao[i].destroy();
218   }
219 
set_draw_vertices(bool b)220   void set_draw_vertices(bool b) {
221     m_draw_vertices = b;
222   }
set_draw_edges(bool b)223   void set_draw_edges(bool b) {
224     m_draw_edges = b;
225   }
set_draw_rays(bool b)226   void set_draw_rays(bool b) {
227     m_draw_rays = b;
228   }
set_draw_lines(bool b)229   void set_draw_lines(bool b) {
230     m_draw_lines = b;
231   }
set_draw_faces(bool b)232   void set_draw_faces(bool b) {
233     m_draw_faces = b;
234   }
set_use_mono_color(bool b)235   void set_use_mono_color(bool b) {
236     m_use_mono_color = b;
237   }
set_inverse_normal(bool b)238   void set_inverse_normal(bool b) {
239     m_inverse_normal = b;
240   }
set_draw_text(bool b)241   void set_draw_text(bool b) {
242     m_draw_text = b;
243   }
244 
clear()245   void clear()
246   {
247     for (unsigned int i=0; i<LAST_INDEX; ++i)
248     { arrays[i].clear(); }
249 
250     m_bounding_box=CGAL::Bbox_3();
251     m_texts.clear();
252   }
253 
is_empty()254   bool is_empty() const
255   {
256     return (m_buffer_for_mono_points.is_empty() &&
257             m_buffer_for_colored_points.is_empty() &&
258             m_buffer_for_mono_segments.is_empty() &&
259             m_buffer_for_colored_segments.is_empty() &&
260             m_buffer_for_mono_rays.is_empty() &&
261             m_buffer_for_colored_rays.is_empty() &&
262             m_buffer_for_mono_lines.is_empty() &&
263             m_buffer_for_colored_lines.is_empty() &&
264             m_buffer_for_mono_faces.is_empty() &&
265             m_buffer_for_colored_faces.is_empty());
266   }
267 
bounding_box()268   const CGAL::Bbox_3& bounding_box() const
269   { return m_bounding_box; }
270 
has_zero_x()271   bool has_zero_x() const
272   {
273     return
274       m_buffer_for_mono_points.has_zero_x() &&
275       m_buffer_for_colored_points.has_zero_x() &&
276       m_buffer_for_mono_segments.has_zero_x() &&
277       m_buffer_for_colored_segments.has_zero_x() &&
278       m_buffer_for_mono_faces.has_zero_x() &&
279       m_buffer_for_colored_faces.has_zero_x() &&
280       m_buffer_for_mono_rays.has_zero_x() &&
281       m_buffer_for_colored_rays.has_zero_x() &&
282       m_buffer_for_mono_lines.has_zero_x() &&
283       m_buffer_for_colored_lines.has_zero_x();
284   }
285 
has_zero_y()286   bool has_zero_y() const
287   {
288     return
289       m_buffer_for_mono_points.has_zero_y() &&
290       m_buffer_for_colored_points.has_zero_y() &&
291       m_buffer_for_mono_segments.has_zero_y() &&
292       m_buffer_for_colored_segments.has_zero_y() &&
293       m_buffer_for_mono_faces.has_zero_y() &&
294       m_buffer_for_colored_faces.has_zero_y() &&
295       m_buffer_for_mono_rays.has_zero_y() &&
296       m_buffer_for_colored_rays.has_zero_y() &&
297       m_buffer_for_mono_lines.has_zero_y() &&
298       m_buffer_for_colored_lines.has_zero_y();
299   }
300 
has_zero_z()301   bool has_zero_z() const
302   {
303     return
304       m_buffer_for_mono_points.has_zero_z() &&
305       m_buffer_for_colored_points.has_zero_z() &&
306       m_buffer_for_mono_segments.has_zero_z() &&
307       m_buffer_for_colored_segments.has_zero_z() &&
308       m_buffer_for_mono_faces.has_zero_z() &&
309       m_buffer_for_colored_faces.has_zero_z() &&
310       m_buffer_for_mono_rays.has_zero_z() &&
311       m_buffer_for_colored_rays.has_zero_z() &&
312       m_buffer_for_mono_lines.has_zero_z() &&
313       m_buffer_for_colored_lines.has_zero_z();
314   }
315 
316   template<typename KPoint>
add_point(const KPoint & p)317   void add_point(const KPoint& p)
318   { m_buffer_for_mono_points.add_point(p); }
319 
320   template<typename KPoint>
add_point(const KPoint & p,const CGAL::IO::Color & acolor)321   void add_point(const KPoint& p, const CGAL::IO::Color& acolor)
322   { m_buffer_for_colored_points.add_point(p, acolor); }
323 
324   template<typename KPoint>
add_segment(const KPoint & p1,const KPoint & p2)325   void add_segment(const KPoint& p1, const KPoint& p2)
326   { m_buffer_for_mono_segments.add_segment(p1, p2); }
327 
328   template<typename KPoint>
add_segment(const KPoint & p1,const KPoint & p2,const CGAL::IO::Color & acolor)329   void add_segment(const KPoint& p1, const KPoint& p2,
330                    const CGAL::IO::Color& acolor)
331   { m_buffer_for_colored_segments.add_segment(p1, p2, acolor); }
332 
333   template <typename KPoint, typename KVector>
update_bounding_box_for_ray(const KPoint & p,const KVector & v)334   void update_bounding_box_for_ray(const KPoint &p, const KVector &v)
335   {
336     Local_point lp = get_local_point(p);
337     Local_vector lv = get_local_vector(v);
338     CGAL::Bbox_3 b = (lp + lv).bbox();
339     m_bounding_box += b;
340   }
341 
342   template <typename KPoint, typename KVector>
update_bounding_box_for_line(const KPoint & p,const KVector & v,const KVector & pv)343   void update_bounding_box_for_line(const KPoint &p, const KVector &v,
344                                     const KVector &pv)
345   {
346     Local_point lp = get_local_point(p);
347     Local_vector lv = get_local_vector(v);
348     Local_vector lpv = get_local_vector(pv);
349 
350     CGAL::Bbox_3 b = lp.bbox() + (lp + lv).bbox() + (lp + lpv).bbox();
351     m_bounding_box += b;
352   }
353 
354   template <typename KPoint, typename KVector>
add_ray(const KPoint & p,const KVector & v)355   void add_ray(const KPoint &p, const KVector &v)
356   {
357     double bigNumber = 1e30;
358     m_buffer_for_mono_rays.add_ray_segment(p, (p + (bigNumber)*v));
359   }
360 
361   template <typename KPoint, typename KVector>
add_ray(const KPoint & p,const KVector & v,const CGAL::IO::Color & acolor)362   void add_ray(const KPoint &p, const KVector &v, const CGAL::IO::Color &acolor)
363   {
364     double bigNumber = 1e30;
365     m_buffer_for_colored_rays.add_ray_segment(p, (p + (bigNumber)*v), acolor);
366   }
367 
368   template <typename KPoint, typename KVector>
add_line(const KPoint & p,const KVector & v)369   void add_line(const KPoint &p, const KVector &v)
370   {
371     double bigNumber = 1e30;
372     m_buffer_for_mono_lines.add_line_segment((p - (bigNumber)*v),
373                                              (p + (bigNumber)*v));
374   }
375 
376   template <typename KPoint, typename KVector>
add_line(const KPoint & p,const KVector & v,const CGAL::IO::Color & acolor)377   void add_line(const KPoint &p, const KVector &v, const CGAL::IO::Color &acolor)
378   {
379     double bigNumber = 1e30;
380     m_buffer_for_colored_lines.add_line_segment((p - (bigNumber)*v),
381                                                 (p + (bigNumber)*v), acolor);
382   }
383 
384   template<typename KPoint>
add_text(const KPoint & kp,const QString & txt)385   void add_text(const KPoint& kp, const QString& txt)
386   {
387     Local_point p=get_local_point(kp);
388     m_texts.push_back(std::make_tuple(p, txt));
389   }
390 
391   template<typename KPoint>
add_text(const KPoint & kp,const char * txt)392   void add_text(const KPoint& kp, const char* txt)
393   { add_text(kp, QString(txt)); }
394 
395   template<typename KPoint>
add_text(const KPoint & kp,const std::string & txt)396   void add_text(const KPoint& kp, const std::string& txt)
397   { add_text(kp, txt.c_str()); }
398 
is_a_face_started()399   bool is_a_face_started() const
400   {
401     return m_buffer_for_mono_faces.is_a_face_started() ||
402       m_buffer_for_colored_faces.is_a_face_started();
403   }
404 
face_begin()405   void face_begin()
406   {
407     if (is_a_face_started())
408     {
409       std::cerr<<"You cannot start a new face before to finish the previous one."<<std::endl;
410     }
411     else
412     { m_buffer_for_mono_faces.face_begin(); }
413   }
414 
face_begin(const CGAL::IO::Color & acolor)415   void face_begin(const CGAL::IO::Color& acolor)
416   {
417     if (is_a_face_started())
418     {
419       std::cerr<<"You cannot start a new face before to finish the previous one."<<std::endl;
420     }
421     else
422     { m_buffer_for_colored_faces.face_begin(acolor); }
423   }
424 
425   template<typename KPoint>
add_point_in_face(const KPoint & kp)426   bool add_point_in_face(const KPoint& kp)
427   {
428     if (m_buffer_for_mono_faces.is_a_face_started())
429     { return m_buffer_for_mono_faces.add_point_in_face(kp); }
430     else if (m_buffer_for_colored_faces.is_a_face_started())
431     { return m_buffer_for_colored_faces.add_point_in_face(kp); }
432     return false;
433   }
434 
435   template<typename KPoint, typename KVector>
add_point_in_face(const KPoint & kp,const KVector & p_normal)436   bool add_point_in_face(const KPoint& kp, const KVector& p_normal)
437   {
438     if (m_buffer_for_mono_faces.is_a_face_started())
439     { return m_buffer_for_mono_faces.add_point_in_face(kp, p_normal); }
440     else if (m_buffer_for_colored_faces.is_a_face_started())
441     { return m_buffer_for_colored_faces.add_point_in_face(kp, p_normal); }
442     return false;
443   }
444 
face_end()445   void face_end()
446   {
447     if (m_buffer_for_mono_faces.is_a_face_started())
448     { m_buffer_for_mono_faces.face_end(); }
449     else if (m_buffer_for_colored_faces.is_a_face_started())
450     { return m_buffer_for_colored_faces.face_end(); }
451   }
452 
redraw()453   virtual void redraw()
454   {
455     initialize_buffers();
456     update();
457   }
458 
459 protected:
460   // Shortcuts to simplify function calls.
461   template<typename KPoint>
get_local_point(const KPoint & p)462   static Local_point get_local_point(const KPoint& p)
463   {
464     return internal::Geom_utils<typename CGAL::Kernel_traits<KPoint>::Kernel, Local_kernel>::
465       get_local_point(p);
466   }
467   template<typename KVector>
get_local_vector(const KVector & v)468   static Local_vector get_local_vector(const KVector& v)
469   {
470     return internal::Geom_utils<typename CGAL::Kernel_traits<KVector>::Kernel, Local_kernel>::
471       get_local_vector(v);
472   }
473 
compile_shaders()474   void compile_shaders()
475   {
476     rendering_program_face.removeAllShaders();
477     rendering_program_p_l.removeAllShaders();
478     rendering_program_clipping_plane.removeAllShaders();
479 
480     // Create the buffers
481     for (unsigned int i=0; i<NB_VBO_BUFFERS; ++i)
482     {
483       if(!buffers[i].isCreated() && !buffers[i].create())
484       { std::cerr<<"VBO Creation number "<<i<<" FAILED"<<std::endl; }
485     }
486 
487     for (unsigned int i=0; i<NB_VAO_BUFFERS; ++i)
488     {
489       if(!vao[i].isCreated() && !vao[i].create())
490       { std::cerr<<"VAO Creation number "<<i<<" FAILED"<<std::endl; }
491     }
492 
493     // Vertices and segments shader
494 
495     const char* source_ = isOpenGL_4_3()
496         ? vertex_source_p_l
497         : vertex_source_p_l_comp;
498 
499     QOpenGLShader *vertex_shader_p_l = new QOpenGLShader(QOpenGLShader::Vertex);
500     if(!vertex_shader_p_l->compileSourceCode(source_))
501     { std::cerr<<"Compiling vertex source FAILED"<<std::endl; }
502 
503     source_ = isOpenGL_4_3()
504         ? fragment_source_p_l
505         : fragment_source_p_l_comp;
506 
507     QOpenGLShader *fragment_shader_p_l= new QOpenGLShader(QOpenGLShader::Fragment);
508     if(!fragment_shader_p_l->compileSourceCode(source_))
509     { std::cerr<<"Compiling fragmentsource FAILED"<<std::endl; }
510 
511     if(!rendering_program_p_l.addShader(vertex_shader_p_l))
512     { std::cerr<<"adding vertex shader FAILED"<<std::endl; }
513     if(!rendering_program_p_l.addShader(fragment_shader_p_l))
514     { std::cerr<<"adding fragment shader FAILED"<<std::endl; }
515     if(!rendering_program_p_l.link())
516     { std::cerr<<"linking Program FAILED"<<std::endl; }
517 
518     // Faces shader
519 
520     source_ = isOpenGL_4_3()
521             ? vertex_source_color
522             : vertex_source_color_comp;
523 
524     QOpenGLShader *vertex_shader_face = new QOpenGLShader(QOpenGLShader::Vertex);
525     if(!vertex_shader_face->compileSourceCode(source_))
526     { std::cerr<<"Compiling vertex source FAILED"<<std::endl; }
527 
528     source_ = isOpenGL_4_3()
529             ? fragment_source_color
530             : fragment_source_color_comp;
531 
532     QOpenGLShader *fragment_shader_face= new QOpenGLShader(QOpenGLShader::Fragment);
533     if(!fragment_shader_face->compileSourceCode(source_))
534     { std::cerr<<"Compiling fragment source FAILED"<<std::endl; }
535 
536     if(!rendering_program_face.addShader(vertex_shader_face))
537     { std::cerr<<"adding vertex shader FAILED"<<std::endl; }
538     if(!rendering_program_face.addShader(fragment_shader_face))
539     { std::cerr<<"adding fragment shader FAILED"<<std::endl; }
540     if(!rendering_program_face.link())
541     { std::cerr<<"linking Program FAILED"<<std::endl; }
542 
543     // clipping plane shader
544 
545 
546     if (isOpenGL_4_3())
547     {
548       source_ = vertex_source_clipping_plane;
549 
550       QOpenGLShader *vertex_shader_clipping_plane = new QOpenGLShader(QOpenGLShader::Vertex);
551       if (!vertex_shader_clipping_plane->compileSourceCode(source_))
552       { std::cerr << "Compiling vertex source for clipping plane FAILED" << std::endl; }
553 
554       source_ = fragment_source_clipping_plane;
555 
556       QOpenGLShader *fragment_shader_clipping_plane = new QOpenGLShader(QOpenGLShader::Fragment);
557       if (!fragment_shader_clipping_plane->compileSourceCode(source_))
558       { std::cerr << "Compiling fragment source for clipping plane FAILED" << std::endl; }
559 
560       if (!rendering_program_clipping_plane.addShader(vertex_shader_clipping_plane))
561       { std::cerr << "Adding vertex shader for clipping plane FAILED" << std::endl;}
562       if (!rendering_program_clipping_plane.addShader(fragment_shader_clipping_plane))
563       { std::cerr << "Adding fragment shader for clipping plane FAILED" << std::endl; }
564       if (!rendering_program_clipping_plane.link())
565       { std::cerr << "Linking Program for clipping plane FAILED" << std::endl; }
566 
567     }
568 
569     // source_ = isOpenGL_4_3()
570     //         ? vertex_source_clipping_plane
571     //         : vertex_source_clipping_plane_comp;
572 
573     // QOpenGLShader *vertex_shader_clipping_plane = new QOpenGLShader(QOpenGLShader::Vertex);
574     // if (!vertex_shader_clipping_plane->compileSourceCode(source_))
575     // { std::cerr << "Compiling vertex source for clipping plane FAILED" << std::endl; }
576 
577     // source_ = isOpenGL_4_3()
578     //         ? fragment_source_clipping_plane
579     //         : fragment_source_clipping_plane_comp;
580 
581     // QOpenGLShader *fragment_shader_clipping_plane = new QOpenGLShader(QOpenGLShader::Fragment);
582     // if (!fragment_shader_clipping_plane->compileSourceCode(source_))
583     // { std::cerr << "Compiling fragment source for clipping plane FAILED" << std::endl; }
584 
585     // if (!rendering_program_clipping_plane.addShader(vertex_shader_clipping_plane))
586     // { std::cerr << "Adding vertex shader for clipping plane FAILED" << std::endl;}
587     // if (!rendering_program_clipping_plane.addShader(fragment_shader_clipping_plane))
588     // { std::cerr << "Adding fragment shader for clipping plane FAILED" << std::endl; }
589     // if (!rendering_program_clipping_plane.link())
590     // { std::cerr << "Linking Program for clipping plane FAILED" << std::endl; }
591   }
592 
initialize_buffers()593   void initialize_buffers()
594   {
595     rendering_program_p_l.bind();
596 
597     // 1) POINT SHADER
598 
599     // 1.1) Mono points
600     vao[VAO_MONO_POINTS].bind();
601 
602     unsigned int bufn = 0;
603     assert(bufn<NB_VBO_BUFFERS);
604     buffers[bufn].bind();
605     buffers[bufn].allocate(arrays[POS_MONO_POINTS].data(),
606                            static_cast<int>(arrays[POS_MONO_POINTS].size()*sizeof(float)));
607     rendering_program_p_l.enableAttributeArray("vertex");
608     rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3);
609 
610     buffers[bufn].release();
611 
612     rendering_program_p_l.disableAttributeArray("color");
613 
614     vao[VAO_MONO_POINTS].release();
615 
616     // 1.2) Color points
617     vao[VAO_COLORED_POINTS].bind();
618 
619     ++bufn;
620     assert(bufn<NB_VBO_BUFFERS);
621     buffers[bufn].bind();
622     buffers[bufn].allocate(arrays[POS_COLORED_POINTS].data(),
623                            static_cast<int>(arrays[POS_COLORED_POINTS].size()*sizeof(float)));
624     rendering_program_p_l.enableAttributeArray("vertex");
625     rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3);
626     buffers[bufn].release();
627 
628     ++bufn;
629     assert(bufn<NB_VBO_BUFFERS);
630     buffers[bufn].bind();
631     buffers[bufn].allocate(arrays[COLOR_POINTS].data(),
632                            static_cast<int>(arrays[COLOR_POINTS].size()*sizeof(float)));
633     rendering_program_p_l.enableAttributeArray("color");
634     rendering_program_p_l.setAttributeBuffer("color",GL_FLOAT,0,3);
635     buffers[bufn].release();
636 
637     vao[VAO_COLORED_POINTS].release();
638 
639     // 2) SEGMENT SHADER
640 
641     // 2.1) Mono segments
642     vao[VAO_MONO_SEGMENTS].bind();
643 
644     ++bufn;
645     assert(bufn<NB_VBO_BUFFERS);
646     buffers[bufn].bind();
647     buffers[bufn].allocate(arrays[POS_MONO_SEGMENTS].data(),
648                            static_cast<int>(arrays[POS_MONO_SEGMENTS].size()*sizeof(float)));
649     rendering_program_p_l.enableAttributeArray("vertex");
650     rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3);
651 
652     buffers[bufn].release();
653 
654     rendering_program_p_l.disableAttributeArray("color");
655 
656     vao[VAO_MONO_SEGMENTS].release();
657 
658     // 2.1) Color segments
659     vao[VAO_COLORED_SEGMENTS].bind();
660 
661     ++bufn;
662     assert(bufn<NB_VBO_BUFFERS);
663     buffers[bufn].bind();
664     buffers[bufn].allocate(arrays[POS_COLORED_SEGMENTS].data(),
665                            static_cast<int>(arrays[POS_COLORED_SEGMENTS].size()*sizeof(float)));
666     rendering_program_p_l.enableAttributeArray("vertex");
667     rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3);
668 
669     buffers[bufn].release();
670 
671     ++bufn;
672     assert(bufn<NB_VBO_BUFFERS);
673     buffers[bufn].bind();
674     buffers[bufn].allocate(arrays[COLOR_SEGMENTS].data(),
675                            static_cast<int>(arrays[COLOR_SEGMENTS].size()*sizeof(float)));
676     rendering_program_p_l.enableAttributeArray("color");
677     rendering_program_p_l.setAttributeBuffer("color",GL_FLOAT,0,3);
678     buffers[bufn].release();
679 
680     vao[VAO_COLORED_SEGMENTS].release();
681 
682     rendering_program_p_l.release();
683 
684     // 3) RAYS SHADER
685 
686     // 3.1) Mono rays
687     vao[VAO_MONO_RAYS].bind();
688 
689     ++bufn;
690     assert(bufn<NB_VBO_BUFFERS);
691     buffers[bufn].bind();
692     buffers[bufn].allocate(arrays[POS_MONO_RAYS].data(),
693                            static_cast<int>(arrays[POS_MONO_RAYS].size()*sizeof(float)));
694     rendering_program_p_l.enableAttributeArray("vertex");
695     rendering_program_p_l.setAttributeArray("vertex",GL_FLOAT,0,3);
696 
697     buffers[bufn].release();
698 
699     rendering_program_p_l.disableAttributeArray("color");
700 
701     vao[VAO_MONO_RAYS].release();
702 
703     // 3.2) Color rays
704 
705     vao[VAO_COLORED_RAYS].bind();
706 
707     ++bufn;
708     assert(bufn<NB_VBO_BUFFERS);
709     buffers[bufn].bind();
710     buffers[bufn].allocate(arrays[POS_COLORED_RAYS].data(),
711                            static_cast<int>(arrays[POS_COLORED_RAYS].size()*sizeof(float)));
712     rendering_program_p_l.enableAttributeArray("vertex");
713     rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3);
714 
715     buffers[bufn].release();
716 
717     ++bufn;
718     assert(bufn<NB_VBO_BUFFERS);
719     buffers[bufn].bind();
720     buffers[bufn].allocate(arrays[COLOR_RAYS].data(),
721                            static_cast<int>(arrays[COLOR_RAYS].size()*sizeof(float)));
722     rendering_program_p_l.enableAttributeArray("color");
723     rendering_program_p_l.setAttributeBuffer("color",GL_FLOAT,0,3);
724     buffers[bufn].release();
725 
726     vao[VAO_COLORED_RAYS].release();
727 
728     rendering_program_p_l.release();
729 
730     // 4) LINES SHADER
731     // 4.1) Mono lines
732     vao[VAO_MONO_LINES].bind();
733 
734     ++bufn;
735     assert(bufn<NB_VBO_BUFFERS);
736     buffers[bufn].bind();
737     buffers[bufn].allocate(arrays[POS_MONO_LINES].data(),
738                            static_cast<int>(arrays[POS_MONO_LINES].size()*sizeof(float)));
739     rendering_program_p_l.enableAttributeArray("vertex");
740     rendering_program_p_l.setAttributeArray("vertex",GL_FLOAT,0,3);
741 
742     buffers[bufn].release();
743 
744     rendering_program_p_l.disableAttributeArray("color");
745 
746     vao[VAO_MONO_LINES].release();
747 
748     // 4.2 Color lines
749 
750     vao[VAO_COLORED_LINES].bind();
751 
752     ++bufn;
753     assert(bufn<NB_VBO_BUFFERS);
754     buffers[bufn].bind();
755     buffers[bufn].allocate(arrays[POS_COLORED_LINES].data(),
756                            static_cast<int>(arrays[POS_COLORED_LINES].size()*sizeof(float)));
757     rendering_program_p_l.enableAttributeArray("vertex");
758     rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3);
759 
760     buffers[bufn].release();
761 
762     ++bufn;
763     assert(bufn<NB_VBO_BUFFERS);
764     buffers[bufn].bind();
765     buffers[bufn].allocate(arrays[COLOR_LINES].data(),
766                            static_cast<int>(arrays[COLOR_LINES].size()*sizeof(float)));
767     rendering_program_p_l.enableAttributeArray("color");
768     rendering_program_p_l.setAttributeBuffer("color",GL_FLOAT,0,3);
769     buffers[bufn].release();
770 
771     vao[VAO_COLORED_LINES].release();
772 
773     rendering_program_p_l.release();
774 
775     // 5) FACE SHADER
776     rendering_program_face.bind();
777 
778     // 5.1) Mono faces
779     vao[VAO_MONO_FACES].bind();
780 
781     // 5.1.1) points of the mono faces
782     ++bufn;
783     assert(bufn<NB_VBO_BUFFERS);
784     buffers[bufn].bind();
785     buffers[bufn].allocate(arrays[POS_MONO_FACES].data(),
786                            static_cast<int>(arrays[POS_MONO_FACES].size()*sizeof(float)));
787     rendering_program_face.enableAttributeArray("vertex");
788     rendering_program_face.setAttributeBuffer("vertex",GL_FLOAT,0,3);
789 
790     buffers[bufn].release();
791 
792     // 5.1.2) normals of the mono faces
793     ++bufn;
794     assert(bufn<NB_VBO_BUFFERS);
795     buffers[bufn].bind();
796     if (m_flatShading)
797     {
798       buffers[bufn].allocate(arrays[FLAT_NORMAL_MONO_FACES].data(),
799                                     static_cast<int>(arrays[FLAT_NORMAL_MONO_FACES].size()*
800                                                      sizeof(float)));
801     }
802     else
803     {
804       buffers[bufn].allocate(arrays[SMOOTH_NORMAL_MONO_FACES].data(),
805                                     static_cast<int>(arrays[SMOOTH_NORMAL_MONO_FACES].size()*
806                                                        sizeof(float)));
807     }
808     rendering_program_face.enableAttributeArray("normal");
809     rendering_program_face.setAttributeBuffer("normal",GL_FLOAT,0,3);
810 
811     buffers[bufn].release();
812 
813     // 5.1.3) color of the mono faces
814     rendering_program_face.disableAttributeArray("color");
815     vao[VAO_MONO_FACES].release();
816 
817     // 5.2) Color faces
818     vao[VAO_COLORED_FACES].bind();
819 
820     // 5.2.1) points of the color faces
821     ++bufn;
822     assert(bufn<NB_VBO_BUFFERS);
823     buffers[bufn].bind();
824     buffers[bufn].allocate(arrays[POS_COLORED_FACES].data(),
825                            static_cast<int>(arrays[POS_COLORED_FACES].size()*sizeof(float)));
826     rendering_program_face.enableAttributeArray("vertex");
827     rendering_program_face.setAttributeBuffer("vertex",GL_FLOAT,0,3);
828 
829     buffers[bufn].release();
830 
831     // 5.2.2) normals of the color faces
832     ++bufn;
833     assert(bufn<NB_VBO_BUFFERS);
834     buffers[bufn].bind();
835     if (m_flatShading)
836     {
837       buffers[bufn].allocate(arrays[FLAT_NORMAL_COLORED_FACES].data(),
838                                     static_cast<int>(arrays[FLAT_NORMAL_COLORED_FACES].size()*
839                                                      sizeof(float)));
840     }
841     else
842     {
843       buffers[bufn].allocate(arrays[SMOOTH_NORMAL_COLORED_FACES].data(),
844                                     static_cast<int>(arrays[SMOOTH_NORMAL_COLORED_FACES].size()*
845                                                      sizeof(float)));
846     }
847     rendering_program_face.enableAttributeArray("normal");
848     rendering_program_face.setAttributeBuffer("normal",GL_FLOAT,0,3);
849 
850     buffers[bufn].release();
851 
852     // 5.2.3) colors of the faces
853     ++bufn;
854     assert(bufn<NB_VBO_BUFFERS);
855     buffers[bufn].bind();
856     buffers[bufn].allocate(arrays[COLOR_FACES].data(),
857                            static_cast<int>(arrays[COLOR_FACES].size()*sizeof(float)));
858     rendering_program_face.enableAttributeArray("color");
859     rendering_program_face.setAttributeBuffer("color",GL_FLOAT,0,3);
860 
861     buffers[bufn].release();
862 
863     vao[VAO_COLORED_FACES].release();
864 
865     rendering_program_face.release();
866 
867 
868     // 6) clipping plane shader
869     if (isOpenGL_4_3())
870     {
871       rendering_program_clipping_plane.bind();
872 
873       vao[VAO_CLIPPING_PLANE].bind();
874       ++bufn;
875       assert(bufn < NB_VBO_BUFFERS);
876       buffers[bufn].bind();
877       buffers[bufn].allocate(arrays[POS_CLIPPING_PLANE].data(),
878                             static_cast<int>(arrays[POS_CLIPPING_PLANE].size() * sizeof(float)));
879       rendering_program_clipping_plane.enableAttributeArray("vertex");
880       rendering_program_clipping_plane.setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
881 
882       buffers[bufn].release();
883 
884       rendering_program_clipping_plane.release();
885     }
886 
887     m_are_buffers_initialized = true;
888   }
889 
attrib_buffers(CGAL::QGLViewer * viewer)890   void attrib_buffers(CGAL::QGLViewer* viewer)
891   {
892     QMatrix4x4 mvpMatrix;
893     QMatrix4x4 mvMatrix;
894     double mat[16];
895     viewer->camera()->getModelViewProjectionMatrix(mat);
896     for(unsigned int i=0; i < 16; i++)
897     {
898       mvpMatrix.data()[i] = (float)mat[i];
899     }
900     viewer->camera()->getModelViewMatrix(mat);
901     for(unsigned int i=0; i < 16; i++)
902     {
903       mvMatrix.data()[i] = (float)mat[i];
904     }
905     // define material
906     QVector4D diffuse( 0.9f,
907                        0.9f,
908                        0.9f,
909                        0.9f );
910 
911     QVector4D specular( 0.0f,
912                         0.0f,
913                         0.0f,
914                         1.0f );
915 
916     CGAL::Bbox_3 bb;
917     if (bb==bounding_box()) // Case of "empty" bounding box
918     {
919       bb=Local_point(CGAL::ORIGIN).bbox();
920       bb=bb + Local_point(1,1,1).bbox(); // To avoid a warning from Qglviewer
921     }
922     else
923     { bb=bounding_box(); }
924 
925     QVector4D position((bb.xmax()-bb.xmin())/2,
926                        (bb.ymax()-bb.ymin())/2,
927                        bb.zmax(), 0.0);
928     GLfloat shininess =  1.0f;
929 
930     rendering_program_face.bind();
931     int mvpLocation = rendering_program_face.uniformLocation("mvp_matrix");
932     int mvLocation = rendering_program_face.uniformLocation("mv_matrix");
933     int lightLocation[5];
934     lightLocation[0] = rendering_program_face.uniformLocation("light_pos");
935     lightLocation[1] = rendering_program_face.uniformLocation("light_diff");
936     lightLocation[2] = rendering_program_face.uniformLocation("light_spec");
937     lightLocation[3] = rendering_program_face.uniformLocation("light_amb");
938     lightLocation[4] = rendering_program_face.uniformLocation("spec_power");
939 
940     rendering_program_face.setUniformValue(lightLocation[0], position);
941     rendering_program_face.setUniformValue(lightLocation[1], diffuse);
942     rendering_program_face.setUniformValue(lightLocation[2], specular);
943     rendering_program_face.setUniformValue(lightLocation[3], m_ambient_color);
944     rendering_program_face.setUniformValue(lightLocation[4], shininess);
945     rendering_program_face.setUniformValue(mvpLocation, mvpMatrix);
946     rendering_program_face.setUniformValue(mvLocation, mvMatrix);
947     rendering_program_face.release();
948 
949     rendering_program_p_l.bind();
950     int mvpLocation2 = rendering_program_p_l.uniformLocation("mvp_matrix");
951     rendering_program_p_l.setUniformValue(mvpLocation2, mvpMatrix);
952     rendering_program_p_l.release();
953 
954 
955     if (isOpenGL_4_3())
956     {
957       QMatrix4x4 clipping_mMatrix;
958       clipping_mMatrix.setToIdentity();
959       if(m_frame_plane)
960       {
961         for(int i=0; i< 16 ; i++)
962           clipping_mMatrix.data()[i] =  m_frame_plane->matrix()[i];
963       }
964 
965       rendering_program_clipping_plane.bind();
966       int vpLocation = rendering_program_clipping_plane.uniformLocation("vp_matrix");
967       int mLocation = rendering_program_clipping_plane.uniformLocation("m_matrix");
968       rendering_program_clipping_plane.setUniformValue(vpLocation, mvpMatrix);
969       rendering_program_clipping_plane.setUniformValue(mLocation, clipping_mMatrix);
970       rendering_program_clipping_plane.release();
971     }
972   }
973 
974   // Returns true if the data structure lies on a plane
is_two_dimensional()975   bool is_two_dimensional() {
976     return (!is_empty() && !m_no_2D_mode &&
977             (has_zero_x() || has_zero_y() || has_zero_z()));
978   }
979 
draw()980   virtual void draw()
981   {
982     glEnable(GL_DEPTH_TEST);
983 
984     QMatrix4x4 clipping_mMatrix;
985     clipping_mMatrix.setToIdentity();
986     if(m_frame_plane)
987     {
988       for(int i=0; i< 16 ; i++)
989         clipping_mMatrix.data()[i] =  m_frame_plane->matrix()[i];
990     }
991     QVector4D clipPlane = clipping_mMatrix * QVector4D(0.0, 0.0, 1.0, 0.0);
992     QVector4D plane_point = clipping_mMatrix * QVector4D(0,0,0,1);
993     if(!m_are_buffers_initialized)
994     { initialize_buffers(); }
995 
996     if (is_two_dimensional())
997     {
998       camera()->setType(CGAL::qglviewer::Camera::ORTHOGRAPHIC);
999       //      Camera Constraint:
1000       constraint.setRotationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::AXIS);
1001       constraint.setTranslationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::FREE);
1002 
1003       double cx=0., cy=0., cz=0.;
1004       if (has_zero_x())      { cx=1.; }
1005       else if (has_zero_y()) { cy=1.; }
1006       else                   { cz=1.; }
1007 
1008       camera()->setViewDirection(CGAL::qglviewer::Vec(-cx,-cy,-cz));
1009       constraint.setRotationConstraintDirection(CGAL::qglviewer::Vec(cx, cy, cz));
1010       camera()->frame()->setConstraint(&constraint);
1011     }
1012     else
1013     {
1014       camera()->setType(CGAL::qglviewer::Camera::PERSPECTIVE);
1015       camera()->frame()->setConstraint(nullptr);
1016     }
1017 
1018     QColor color;
1019     attrib_buffers(this);
1020 
1021     if(m_draw_vertices)
1022     {
1023       rendering_program_p_l.bind();
1024 
1025       // rendering_mode == -1: draw all
1026       // rendering_mode == 0: draw inside clipping plane
1027       // rendering_mode == 1: draw outside clipping plane
1028       auto renderer = [this, &color, &clipPlane, &plane_point](float rendering_mode) {
1029         vao[VAO_MONO_POINTS].bind();
1030         color.setRgbF((double)m_vertices_mono_color.red()/(double)255,
1031                       (double)m_vertices_mono_color.green()/(double)255,
1032                       (double)m_vertices_mono_color.blue()/(double)255);
1033         rendering_program_p_l.setAttributeValue("color",color);
1034         rendering_program_p_l.setUniformValue("point_size", GLfloat(m_size_points));
1035         rendering_program_p_l.setUniformValue("clipPlane", clipPlane);
1036         rendering_program_p_l.setUniformValue("pointPlane", plane_point);
1037         rendering_program_p_l.setUniformValue("rendering_mode", rendering_mode);
1038         glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(arrays[POS_MONO_POINTS].size()/3));
1039         vao[VAO_MONO_POINTS].release();
1040 
1041         vao[VAO_COLORED_POINTS].bind();
1042         if (m_use_mono_color)
1043         {
1044           color.setRgbF((double)m_vertices_mono_color.red()/(double)255,
1045                         (double)m_vertices_mono_color.green()/(double)255,
1046                       (double)m_vertices_mono_color.blue()/(double)255);
1047           rendering_program_p_l.disableAttributeArray("color");
1048           rendering_program_p_l.setAttributeValue("color",color);
1049         }
1050         else
1051         {
1052           rendering_program_p_l.enableAttributeArray("color");
1053         }
1054         rendering_program_p_l.setUniformValue("point_size", GLfloat(m_size_points));
1055         rendering_program_p_l.setUniformValue("clipPlane", clipPlane);
1056         rendering_program_p_l.setUniformValue("pointPlane", plane_point);
1057         rendering_program_p_l.setUniformValue("rendering_mode", rendering_mode);
1058         glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(arrays[POS_COLORED_POINTS].size()/3));
1059         vao[VAO_COLORED_POINTS].release();
1060       };
1061 
1062       enum {
1063         DRAW_ALL = -1, // draw all
1064         DRAW_INSIDE_ONLY, // draw only the part inside the clipping plane
1065         DRAW_OUTSIDE_ONLY // draw only the part outside the clipping plane
1066       };
1067 
1068       if (m_use_clipping_plane == CLIPPING_PLANE_SOLID_HALF_ONLY)
1069       {
1070         renderer(DRAW_INSIDE_ONLY);
1071       }
1072       else
1073       {
1074         renderer(DRAW_ALL);
1075       }
1076 
1077       rendering_program_p_l.release();
1078     }
1079 
1080     if(m_draw_edges)
1081     {
1082       rendering_program_p_l.bind();
1083 
1084       // rendering_mode == -1: draw all
1085       // rendering_mode == 0: draw inside clipping plane
1086       // rendering_mode == 1: draw outside clipping plane
1087       auto renderer = [this, &color, &clipPlane, &plane_point](float rendering_mode) {
1088         vao[VAO_MONO_SEGMENTS].bind();
1089         color.setRgbF((double)m_edges_mono_color.red()/(double)255,
1090                       (double)m_edges_mono_color.green()/(double)255,
1091                       (double)m_edges_mono_color.blue()/(double)255);
1092         rendering_program_p_l.setAttributeValue("color",color);
1093         rendering_program_p_l.setUniformValue("clipPlane", clipPlane);
1094         rendering_program_p_l.setUniformValue("pointPlane", plane_point);
1095         rendering_program_p_l.setUniformValue("rendering_mode", rendering_mode);
1096         glLineWidth(m_size_edges);
1097         glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(arrays[POS_MONO_SEGMENTS].size()/3));
1098         vao[VAO_MONO_SEGMENTS].release();
1099 
1100         vao[VAO_COLORED_SEGMENTS].bind();
1101         if (m_use_mono_color)
1102         {
1103           color.setRgbF((double)m_edges_mono_color.red()/(double)255,
1104                         (double)m_edges_mono_color.green()/(double)255,
1105                         (double)m_edges_mono_color.blue()/(double)255);
1106           rendering_program_p_l.disableAttributeArray("color");
1107           rendering_program_p_l.setAttributeValue("color",color);
1108         }
1109         else
1110         {
1111           rendering_program_p_l.enableAttributeArray("color");
1112         }
1113         rendering_program_p_l.setUniformValue("clipPlane", clipPlane);
1114         rendering_program_p_l.setUniformValue("pointPlane", plane_point);
1115         rendering_program_p_l.setUniformValue("rendering_mode", rendering_mode);
1116         glLineWidth(m_size_edges);
1117         glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(arrays[POS_COLORED_SEGMENTS].size()/3));
1118         vao[VAO_COLORED_SEGMENTS].release();
1119       };
1120 
1121       enum {
1122         DRAW_ALL = -1, // draw all
1123         DRAW_INSIDE_ONLY, // draw only the part inside the clipping plane
1124         DRAW_OUTSIDE_ONLY // draw only the part outside the clipping plane
1125       };
1126 
1127       if (m_use_clipping_plane == CLIPPING_PLANE_SOLID_HALF_ONLY)
1128       {
1129         renderer(DRAW_INSIDE_ONLY);
1130       }
1131       else
1132       {
1133         renderer(DRAW_ALL);
1134       }
1135 
1136       rendering_program_p_l.release();
1137     }
1138 
1139     if(m_draw_rays)
1140     {
1141         rendering_program_p_l.bind();
1142 
1143         vao[VAO_MONO_RAYS].bind();
1144         color.setRgbF((double)m_rays_mono_color.red()/(double)255,
1145                       (double)m_rays_mono_color.green()/(double)255,
1146                       (double)m_rays_mono_color.blue()/(double)255);
1147         rendering_program_p_l.setAttributeValue("color",color);
1148         glLineWidth(m_size_rays);
1149         glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(arrays[POS_MONO_RAYS].size()/3));
1150         vao[VAO_MONO_RAYS].release();
1151 
1152         vao[VAO_COLORED_RAYS].bind();
1153         if (m_use_mono_color)
1154         {
1155             color.setRgbF((double)m_rays_mono_color.red()/(double)255,
1156                           (double)m_rays_mono_color.green()/(double)255,
1157                           (double)m_rays_mono_color.blue()/(double)255);
1158             rendering_program_p_l.disableAttributeArray("color");
1159             rendering_program_p_l.setAttributeValue("color",color);
1160         }
1161         else
1162         {
1163             rendering_program_p_l.enableAttributeArray("color");
1164         }
1165         glLineWidth(m_size_rays);
1166         glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(arrays[POS_COLORED_RAYS].size()/3));
1167         vao[VAO_COLORED_RAYS].release();
1168 
1169         rendering_program_p_l.release();
1170     }
1171 
1172     if(m_draw_lines)
1173     {
1174         rendering_program_p_l.bind();
1175 
1176         vao[VAO_MONO_LINES].bind();
1177         color.setRgbF((double)m_lines_mono_color.red()/(double)255,
1178                       (double)m_lines_mono_color.green()/(double)255,
1179                       (double)m_lines_mono_color.blue()/(double)255);
1180         rendering_program_p_l.setAttributeValue("color",color);
1181         glLineWidth(m_size_lines);
1182         glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(arrays[POS_MONO_LINES].size()/3));
1183         vao[VAO_MONO_LINES].release();
1184 
1185         rendering_program_p_l.release();
1186 
1187         vao[VAO_COLORED_LINES].bind();
1188         if (m_use_mono_color)
1189         {
1190             color.setRgbF((double)m_rays_mono_color.red()/(double)255,
1191                           (double)m_rays_mono_color.green()/(double)255,
1192                           (double)m_rays_mono_color.blue()/(double)255);
1193             rendering_program_p_l.disableAttributeArray("color");
1194             rendering_program_p_l.setAttributeValue("color",color);
1195         }
1196         else
1197         {
1198             rendering_program_p_l.enableAttributeArray("color");
1199         }
1200         glLineWidth(m_size_lines);
1201         glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(arrays[POS_COLORED_LINES].size()/3));
1202         vao[VAO_COLORED_LINES].release();
1203 
1204         rendering_program_p_l.release();
1205     }
1206 
1207     // Fix Z-fighting by drawing faces at a depth
1208     GLfloat offset_factor;
1209     GLfloat offset_units;
1210     if (is_two_dimensional()) {
1211       glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &offset_factor);
1212       glGetFloatv(GL_POLYGON_OFFSET_UNITS, &offset_units);
1213       glPolygonOffset(0.1f, 0.9f);
1214     }
1215 
1216     if (m_draw_faces)
1217     {
1218       rendering_program_face.bind();
1219 
1220       // reference: https://stackoverflow.com/questions/37780345/opengl-how-to-create-order-independent-transparency
1221       // rendering_mode == -1: draw all as solid;
1222       // rendering_mode == 0: draw solid only;
1223       // rendering_mode == 1: draw transparent only;
1224       auto renderer = [this, &color, &clipPlane, &plane_point](float rendering_mode) {
1225 
1226       vao[VAO_MONO_FACES].bind();
1227       color.setRgbF((double)m_faces_mono_color.red()/(double)255,
1228                     (double)m_faces_mono_color.green()/(double)255,
1229                     (double)m_faces_mono_color.blue()/(double)255);
1230       rendering_program_face.setAttributeValue("color",color);
1231       rendering_program_face.setUniformValue("rendering_mode", rendering_mode);
1232       rendering_program_face.setUniformValue("rendering_transparency", clipping_plane_rendering_transparency);
1233       rendering_program_face.setUniformValue("clipPlane", clipPlane);
1234       rendering_program_face.setUniformValue("pointPlane", plane_point);
1235       glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(arrays[POS_MONO_FACES].size()/3));
1236       vao[VAO_MONO_FACES].release();
1237 
1238         vao[VAO_COLORED_FACES].bind();
1239         if (m_use_mono_color)
1240         {
1241           color.setRgbF((double)m_faces_mono_color.red()/(double)255,
1242                         (double)m_faces_mono_color.green()/(double)255,
1243                         (double)m_faces_mono_color.blue()/(double)255);
1244           rendering_program_face.disableAttributeArray("color");
1245           rendering_program_face.setAttributeValue("color",color);
1246         }
1247         else
1248         {
1249           rendering_program_face.enableAttributeArray("color");
1250         }
1251         rendering_program_face.setUniformValue("rendering_mode", rendering_mode);
1252         rendering_program_face.setUniformValue("rendering_transparency", clipping_plane_rendering_transparency);
1253         rendering_program_face.setUniformValue("clipPlane", clipPlane);
1254         rendering_program_face.setUniformValue("pointPlane", plane_point);
1255         glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(arrays[POS_COLORED_FACES].size()/3));
1256         vao[VAO_COLORED_FACES].release();
1257       };
1258 
1259       auto renderer_clipping_plane = [this](bool clipping_plane_rendering) {
1260         if (!isOpenGL_4_3()) return;
1261         if (!clipping_plane_rendering) return;
1262         // render clipping plane here
1263         rendering_program_clipping_plane.bind();
1264         vao[VAO_CLIPPING_PLANE].bind();
1265         glLineWidth(0.1f);
1266         glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(arrays[POS_CLIPPING_PLANE].size() / 3));
1267         glLineWidth(1.0f);
1268         vao[VAO_CLIPPING_PLANE].release();
1269         rendering_program_clipping_plane.release();
1270       };
1271 
1272       enum {
1273         DRAW_SOLID_ALL = -1, // draw all mesh in solid mode
1274         DRAW_SOLID_HALF, // draw only the mesh inside the clipping plane as solid
1275         DRAW_TRANSPARENT_HALF // draw only the mesh outside the clipping plane as transparent
1276       };
1277 
1278       if (m_use_clipping_plane == CLIPPING_PLANE_SOLID_HALF_TRANSPARENT_HALF)
1279       {
1280         // The z-buffer will prevent transparent objects from being displayed behind other transparent objects.
1281         // Before rendering all transparent objects, disable z-testing first.
1282 
1283         // 1. draw solid first
1284         renderer(DRAW_SOLID_HALF);
1285 
1286         // 2. draw transparent layer second with back face culling to avoid messy triangles
1287         glDepthMask(false); //disable z-testing
1288         glEnable(GL_BLEND);
1289         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1290         glEnable(GL_CULL_FACE);
1291         glCullFace(GL_BACK);
1292         glFrontFace(GL_CW);
1293         renderer(DRAW_TRANSPARENT_HALF);
1294 
1295         // 3. draw solid again without culling and blend to make sure the solid mesh is visible
1296         glDepthMask(true); //enable z-testing
1297         glDisable(GL_CULL_FACE);
1298         glDisable(GL_BLEND);
1299         renderer(DRAW_SOLID_HALF);
1300 
1301         // 4. render clipping plane here
1302         renderer_clipping_plane(clipping_plane_rendering);
1303       }
1304       else if (m_use_clipping_plane == CLIPPING_PLANE_SOLID_HALF_WIRE_HALF ||
1305                m_use_clipping_plane == CLIPPING_PLANE_SOLID_HALF_ONLY)
1306       {
1307         // 1. draw solid HALF
1308         renderer(DRAW_SOLID_HALF);
1309 
1310         // 2. render clipping plane here
1311         renderer_clipping_plane(clipping_plane_rendering);
1312       }
1313       else
1314       {
1315         // 1. draw solid FOR ALL
1316         renderer(DRAW_SOLID_ALL);
1317       }
1318 
1319       if (is_two_dimensional())
1320         glPolygonOffset(offset_factor, offset_units);
1321 
1322       rendering_program_face.release();
1323     }
1324 
1325     if (m_draw_text)
1326     {
1327       glDisable(GL_LIGHTING);
1328       for (std::size_t i=0; i<m_texts.size(); ++i)
1329       {
1330         CGAL::qglviewer::Vec screenPos=camera()->projectedCoordinatesOf
1331           (CGAL::qglviewer::Vec(std::get<0>(m_texts[i]).x(),
1332                                 std::get<0>(m_texts[i]).y(),
1333                                 std::get<0>(m_texts[i]).z()));
1334 
1335         drawText((int)screenPos[0], (int)screenPos[1], std::get<1>(m_texts[i]));
1336       }
1337       glEnable(GL_LIGHTING);
1338     }
1339 
1340     // Multiply matrix to get in the frame coordinate system.
1341     // glMultMatrixd(manipulatedFrame()->matrix()); // Linker error
1342     // Scale down the drawings
1343     // glScalef(0.3f, 0.3f, 0.3f); // Linker error
1344     // Draw an axis using the QGLViewer static function
1345     // drawAxis();
1346   }
1347 
init()1348   virtual void init()
1349   {
1350     initializeOpenGLFunctions();
1351 
1352     // Light default parameters
1353     glLineWidth(m_size_edges);
1354     glEnable(GL_POLYGON_OFFSET_FILL);
1355     glPolygonOffset(1.f,1.f);
1356     glClearColor(1.0f,1.0f,1.0f,0.0f);
1357     glDisable(GL_BLEND);
1358     glEnable(GL_LINE_SMOOTH);
1359     glDisable(GL_POLYGON_SMOOTH_HINT);
1360     glBlendFunc(GL_ONE, GL_ZERO);
1361     glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
1362 
1363     compile_shaders();
1364 
1365     CGAL::Bbox_3 bb;
1366     if (bb==bounding_box()) // Case of "empty" bounding box
1367     {
1368       bb=Local_point(CGAL::ORIGIN).bbox();
1369       bb=bb + Local_point(1,1,1).bbox(); // To avoid a warning from Qglviewer
1370     }
1371     else
1372     { bb=bounding_box(); }
1373     this->camera()->setSceneBoundingBox(CGAL::qglviewer::Vec(bb.xmin(),
1374                                                        bb.ymin(),
1375                                                        bb.zmin()),
1376                                         CGAL::qglviewer::Vec(bb.xmax(),
1377                                                        bb.ymax(),
1378                                                        bb.zmax()));
1379 
1380     // init clipping plane array
1381     auto generate_clipping_plane = [this](qreal size, int nbSubdivisions)
1382     {
1383       for (int i = 0; i <= nbSubdivisions; i++)
1384       {
1385         const float pos = float(size*(2.0*i/nbSubdivisions-1.0));
1386         arrays[POS_CLIPPING_PLANE].push_back(pos);
1387         arrays[POS_CLIPPING_PLANE].push_back(float(-size));
1388         arrays[POS_CLIPPING_PLANE].push_back(0.f);
1389 
1390         arrays[POS_CLIPPING_PLANE].push_back(pos);
1391         arrays[POS_CLIPPING_PLANE].push_back(float(+size));
1392         arrays[POS_CLIPPING_PLANE].push_back(0.f);
1393 
1394         arrays[POS_CLIPPING_PLANE].push_back(float(-size));
1395         arrays[POS_CLIPPING_PLANE].push_back(pos);
1396         arrays[POS_CLIPPING_PLANE].push_back(0.f);
1397 
1398         arrays[POS_CLIPPING_PLANE].push_back(float(size));
1399         arrays[POS_CLIPPING_PLANE].push_back(pos);
1400         arrays[POS_CLIPPING_PLANE].push_back(0.f);
1401       }
1402     };
1403     clipping_plane_rendering_size = ((bb.xmax() - bb.xmin()) + (bb.ymax() - bb.ymin()) + (bb.zmax() - bb.zmin())) / 3;
1404     generate_clipping_plane(3.0 * clipping_plane_rendering_size, 30);
1405 
1406     this->showEntireScene();
1407   }
1408 
negate_all_normals()1409   void negate_all_normals()
1410   {
1411     m_buffer_for_mono_faces.negate_normals();
1412     m_buffer_for_colored_faces.negate_normals();
1413   }
1414 
keyPressEvent(QKeyEvent * e)1415   virtual void keyPressEvent(QKeyEvent *e)
1416   {
1417     const ::Qt::KeyboardModifiers modifiers = e->modifiers();
1418 
1419     if ((e->key()==::Qt::Key_C) && (modifiers==::Qt::NoButton))
1420     {
1421       if (!isOpenGL_4_3()) return;
1422       if (!is_two_dimensional())
1423       {
1424         // toggle clipping plane
1425         m_use_clipping_plane = (m_use_clipping_plane + 1) % CLIPPING_PLANE_END_INDEX;
1426         if (m_use_clipping_plane==CLIPPING_PLANE_OFF && m_frame_plane)
1427         {
1428           setManipulatedFrame(nullptr);
1429           delete m_frame_plane;
1430           m_frame_plane=nullptr;
1431         }
1432         else if (m_frame_plane==nullptr)
1433         {
1434           m_frame_plane=new CGAL::qglviewer::ManipulatedFrame;
1435           setManipulatedFrame(m_frame_plane);
1436         }
1437 
1438         switch(m_use_clipping_plane)
1439         {
1440         case CLIPPING_PLANE_OFF: displayMessage(QString("Draw clipping = flase")); break;
1441         case CLIPPING_PLANE_SOLID_HALF_TRANSPARENT_HALF: clipping_plane_rendering=true; displayMessage(QString("Draw clipping = solid half & transparent half")); break;
1442         case CLIPPING_PLANE_SOLID_HALF_WIRE_HALF: displayMessage(QString("Draw clipping = solid half & wireframe half")); break;
1443         case CLIPPING_PLANE_SOLID_HALF_ONLY: displayMessage(QString("Draw clipping = solid half only")); break;
1444         default: break;
1445         }
1446         update();
1447       }
1448     }
1449 
1450     else if ((e->key()==::Qt::Key_C) && (modifiers==::Qt::AltModifier))
1451     {
1452       if (!isOpenGL_4_3()) return;
1453       if (m_use_clipping_plane!=CLIPPING_PLANE_OFF)
1454       {
1455         clipping_plane_rendering = !clipping_plane_rendering;
1456         displayMessage(QString("Draw clipping plane=%1.").arg(clipping_plane_rendering?"true":"false"));
1457         update();
1458       }
1459     }
1460     else if ((e->key()==::Qt::Key_E) && (modifiers==::Qt::NoButton))
1461     {
1462       m_draw_edges=!m_draw_edges;
1463       displayMessage(QString("Draw edges=%1.").arg(m_draw_edges?"true":"false"));
1464       update();
1465     }
1466     else if ((e->key()==::Qt::Key_M) && (modifiers==::Qt::NoButton))
1467     {
1468       m_use_mono_color=!m_use_mono_color;
1469       displayMessage(QString("Mono color=%1.").arg(m_use_mono_color?"true":"false"));
1470       update();
1471     }
1472     else if ((e->key()==::Qt::Key_N) && (modifiers==::Qt::NoButton))
1473     {
1474       m_inverse_normal=!m_inverse_normal;
1475       displayMessage(QString("Inverse normal=%1.").arg(m_inverse_normal?"true":"false"));
1476       negate_all_normals();
1477       redraw();
1478     }
1479     else if ((e->key()==::Qt::Key_S) && (modifiers==::Qt::NoButton))
1480     {
1481       m_flatShading=!m_flatShading;
1482       if (m_flatShading)
1483         displayMessage("Flat shading.");
1484       else
1485         displayMessage("Gouraud shading.");
1486       redraw();
1487     }
1488     else if ((e->key()==::Qt::Key_T) && (modifiers==::Qt::NoButton))
1489     {
1490       m_draw_text=!m_draw_text;
1491       displayMessage(QString("Draw text=%1.").arg(m_draw_text?"true":"false"));
1492       update();
1493     }
1494     else if ((e->key()==::Qt::Key_U) && (modifiers==::Qt::NoButton))
1495     {
1496       if (is_two_dimensional())
1497       {
1498         displayMessage(QString("Move camera direction upside down."));
1499         /* CGAL::qglviewer::Vec cur=camera()->viewDirection();
1500         double cx=cur.x, cy=cur.y, cz=cur.z;
1501         if (has_zero_x())      { cx=-cx; }
1502         else if (has_zero_y()) { cy=-cy; }
1503         else                   { cz=-cz; }
1504         double cx=0., cy=0., cz=0.;
1505         if (has_zero_x())      { cx=(cur.x<0?-1.:1); }
1506         else if (has_zero_y()) { cy=(cur.y<0?-1.:1); }
1507         else                   { cz=(cur.z<0?-1.:1); }*/
1508 
1509         camera()->setUpVector(-camera()->upVector());
1510         //camera()->frame()->setConstraint(NULL);
1511         // camera()->setViewDirection(CGAL::qglviewer::Vec(-cx,-cy,-cz));
1512         //constraint.setRotationConstraintDirection(CGAL::qglviewer::Vec(cx, cy, cz));
1513         //camera()->frame()->setConstraint(&constraint);
1514         //update();
1515         redraw();
1516       }
1517     }
1518     else if ((e->key()==::Qt::Key_V) && (modifiers==::Qt::NoButton))
1519     {
1520       m_draw_vertices=!m_draw_vertices;
1521       displayMessage(QString("Draw vertices=%1.").arg(m_draw_vertices?"true":"false"));
1522       update();
1523     }
1524     else if ((e->key()==::Qt::Key_W) && (modifiers==::Qt::NoButton))
1525     {
1526       m_draw_faces=!m_draw_faces;
1527       displayMessage(QString("Draw faces=%1.").arg(m_draw_faces?"true":"false"));
1528       update();
1529     }
1530     else if ((e->key()==::Qt::Key_Plus) && (!modifiers.testFlag(::Qt::ControlModifier))) // No ctrl
1531     {
1532       m_size_edges+=.5;
1533       displayMessage(QString("Size of edges=%1.").arg(m_size_edges));
1534       update();
1535     }
1536     else if ((e->key()==::Qt::Key_Minus) && (!modifiers.testFlag(::Qt::ControlModifier))) // No ctrl
1537     {
1538       if (m_size_edges>.5) m_size_edges-=.5;
1539       displayMessage(QString("Size of edges=%1.").arg(m_size_edges));
1540       update();
1541     }
1542     else if ((e->key()==::Qt::Key_Plus) && (modifiers.testFlag(::Qt::ControlModifier)))
1543     {
1544       m_size_points+=.5;
1545       displayMessage(QString("Size of points=%1.").arg(m_size_points));
1546       update();
1547     }
1548     else if ((e->key()==::Qt::Key_Minus) && (modifiers.testFlag(::Qt::ControlModifier)))
1549     {
1550       if (m_size_points>.5) m_size_points-=.5;
1551       displayMessage(QString("Size of points=%1.").arg(m_size_points));
1552       update();
1553     }
1554     else if ((e->key()==::Qt::Key_PageUp) && (modifiers==::Qt::NoButton))
1555     {
1556       m_ambient_color.setX(m_ambient_color.x()+.1);
1557       if (m_ambient_color.x()>1.) m_ambient_color.setX(1.);
1558       m_ambient_color.setY(m_ambient_color.x()+.1);
1559       if (m_ambient_color.y()>1.) m_ambient_color.setY(1.);
1560       m_ambient_color.setZ(m_ambient_color.x()+.1);
1561       if (m_ambient_color.z()>1.) m_ambient_color.setZ(1.);
1562       displayMessage(QString("Light color=(%1 %2 %3).").
1563                      arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z()));
1564       update();
1565     }
1566     else if ((e->key()==::Qt::Key_PageDown) && (modifiers==::Qt::NoButton))
1567     {
1568       m_ambient_color.setX(m_ambient_color.x()-.1);
1569       if (m_ambient_color.x()<0.) m_ambient_color.setX(0.);
1570       m_ambient_color.setY(m_ambient_color.y()-.1);
1571       if (m_ambient_color.y()<0.) m_ambient_color.setY(0.);
1572       m_ambient_color.setZ(m_ambient_color.z()-.1);
1573       if (m_ambient_color.z()<0.) m_ambient_color.setZ(0.);
1574       displayMessage(QString("Light color=(%1 %2 %3).").
1575                      arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z()));
1576       update();
1577     }
1578     else if ((e->key()==::Qt::Key_PageUp) && (modifiers==::Qt::ShiftModifier))
1579     {
1580       m_ambient_color.setX(m_ambient_color.x()+.1);
1581       if (m_ambient_color.x()>1.) m_ambient_color.setX(1.);
1582       displayMessage(QString("Light color=(%1 %2 %3).").
1583                      arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z()));
1584       update();
1585     }
1586     else if ((e->key()==::Qt::Key_PageUp) && (modifiers==::Qt::AltModifier))
1587     {
1588       m_ambient_color.setY(m_ambient_color.y()+.1);
1589       if (m_ambient_color.y()>1.) m_ambient_color.setY(1.);
1590       displayMessage(QString("Light color=(%1 %2 %3).").
1591                      arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z()));
1592       update();
1593     }
1594     else if ((e->key()==::Qt::Key_PageUp) && (modifiers==::Qt::ControlModifier))
1595     {
1596       m_ambient_color.setZ(m_ambient_color.z()+.1);
1597       if (m_ambient_color.z()>1.) m_ambient_color.setZ(1.);
1598       displayMessage(QString("Light color=(%1 %2 %3).").
1599                      arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z()));
1600       update();
1601     }
1602     else if ((e->key()==::Qt::Key_PageDown) && (modifiers==::Qt::ShiftModifier))
1603     {
1604       m_ambient_color.setX(m_ambient_color.x()-.1);
1605       if (m_ambient_color.x()<0.) m_ambient_color.setX(0.);
1606       displayMessage(QString("Light color=(%1 %2 %3).").
1607                      arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z()));
1608       update();
1609     }
1610     else if ((e->key()==::Qt::Key_PageDown) && (modifiers==::Qt::AltModifier))
1611     {
1612       m_ambient_color.setY(m_ambient_color.y()-.1);
1613       if (m_ambient_color.y()<0.) m_ambient_color.setY(0.);
1614       displayMessage(QString("Light color=(%1 %2 %3).").
1615                      arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z()));
1616       update();
1617     }
1618     else if ((e->key()==::Qt::Key_PageDown) && (modifiers==::Qt::ControlModifier))
1619     {
1620       m_ambient_color.setZ(m_ambient_color.z()-.1);
1621       if (m_ambient_color.z()<0.) m_ambient_color.setZ(0.);
1622       displayMessage(QString("Light color=(%1 %2 %3).").
1623                      arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z()));
1624       update();
1625     }
1626     else if ((e->key()==::Qt::Key_O) && (modifiers==::Qt::NoButton))
1627     {
1628       bool old_2D=is_two_dimensional();
1629       m_no_2D_mode=!m_no_2D_mode;
1630       if (old_2D!=is_two_dimensional())
1631       {
1632         if (is_two_dimensional())
1633         { displayMessage(QString("Viewer is in 2D mode.")); }
1634         else { displayMessage(QString("Viewer is in 3D mode.")); }
1635         update();
1636       }
1637     }
1638     else
1639       CGAL::QGLViewer::keyPressEvent(e);
1640   }
1641 
helpString()1642   virtual QString helpString() const
1643   { return helpString("CGAL Basic Viewer"); }
1644 
helpString(const char * title)1645   virtual QString helpString(const char* title) const
1646   {
1647     QString text(QString("<h2>")+QString(title)+QString("</h2>"));
1648     text += "Use the mouse to move the camera around the object. ";
1649     text += "You can respectively revolve around, zoom and translate with "
1650       "the three mouse buttons. ";
1651     text += "Left and middle buttons pressed together rotate around the "
1652       "camera view direction axis<br><br>";
1653     text += "Pressing <b>Alt</b> and one of the function keys "
1654       "(<b>F1</b>..<b>F12</b>) defines a camera keyFrame. ";
1655     text += "Simply press the function key again to restore it. "
1656       "Several keyFrames define a ";
1657     text += "camera path. Paths are saved when you quit the application "
1658       "and restored at next start.<br><br>";
1659     text += "Press <b>F</b> to display the frame rate, <b>A</b> for the "
1660       "world axis, ";
1661     text += "<b>Alt+Return</b> for full screen mode and <b>Control+S</b> "
1662       "to save a snapshot. ";
1663     text += "See the <b>Keyboard</b> tab in this window for a complete "
1664       "shortcut list.<br><br>";
1665     text += "Double clicks automates single click actions: A left button "
1666       "double click aligns the closer axis with the camera (if close enough). ";
1667     text += "A middle button double click fits the zoom of the camera and "
1668       "the right button re-centers the scene.<br><br>";
1669     text += "A left button double click while holding right button pressed "
1670       "defines the camera <i>Revolve Around Point</i>. ";
1671     text += "See the <b>Mouse</b> tab and the documentation web pages for "
1672       "details.<br><br>";
1673     text += "Press <b>Escape</b> to exit the viewer.";
1674     return text;
1675   }
1676 
1677 protected:
1678   bool m_draw_vertices;
1679   bool m_draw_edges;
1680   bool m_draw_rays;
1681   bool m_draw_lines;
1682   bool m_draw_faces;
1683   bool m_flatShading;
1684   bool m_use_mono_color;
1685   bool m_inverse_normal;
1686   bool m_draw_text;
1687   bool m_no_2D_mode;
1688 
1689   enum {
1690     CLIPPING_PLANE_OFF = 0,
1691     CLIPPING_PLANE_SOLID_HALF_TRANSPARENT_HALF,
1692     CLIPPING_PLANE_SOLID_HALF_WIRE_HALF,
1693     CLIPPING_PLANE_SOLID_HALF_ONLY,
1694     CLIPPING_PLANE_END_INDEX
1695   };
1696 
1697   int m_use_clipping_plane=CLIPPING_PLANE_OFF;
1698   CGAL::qglviewer::ManipulatedFrame* m_frame_plane=nullptr;
1699 
1700   double m_size_points;
1701   double m_size_edges;
1702   double m_size_rays;
1703   double m_size_lines;
1704 
1705   CGAL::IO::Color m_vertices_mono_color;
1706   CGAL::IO::Color m_edges_mono_color;
1707   CGAL::IO::Color m_rays_mono_color;
1708   CGAL::IO::Color m_lines_mono_color;
1709   CGAL::IO::Color m_faces_mono_color;
1710   QVector4D   m_ambient_color;
1711 
1712   bool m_are_buffers_initialized;
1713   CGAL::Bbox_3 m_bounding_box;
1714 
1715   // CGAL::qglviewer::LocalConstraint constraint;
1716   CGAL::qglviewer::WorldConstraint constraint;
1717 
1718   // The following enum gives the indices of different elements of arrays vectors.
1719   enum
1720   {
1721     BEGIN_POS=0,
1722     POS_MONO_POINTS=BEGIN_POS,
1723     POS_COLORED_POINTS,
1724     POS_MONO_SEGMENTS,
1725     POS_COLORED_SEGMENTS,
1726     POS_MONO_RAYS,
1727     POS_COLORED_RAYS,
1728     POS_MONO_LINES,
1729     POS_COLORED_LINES,
1730     POS_MONO_FACES,
1731     POS_COLORED_FACES,
1732     POS_CLIPPING_PLANE,
1733     END_POS,
1734     BEGIN_COLOR=END_POS,
1735     COLOR_POINTS=BEGIN_COLOR,
1736     COLOR_SEGMENTS,
1737     COLOR_RAYS,
1738     COLOR_LINES,
1739     COLOR_FACES,
1740     END_COLOR,
1741     BEGIN_NORMAL=END_COLOR,
1742     SMOOTH_NORMAL_MONO_FACES=BEGIN_NORMAL,
1743     FLAT_NORMAL_MONO_FACES,
1744     SMOOTH_NORMAL_COLORED_FACES,
1745     FLAT_NORMAL_COLORED_FACES,
1746     END_NORMAL,
1747     LAST_INDEX=END_NORMAL
1748   };
1749   std::vector<float> arrays[LAST_INDEX];
1750 
1751   Buffer_for_vao<float> m_buffer_for_mono_points;
1752   Buffer_for_vao<float> m_buffer_for_colored_points;
1753   Buffer_for_vao<float> m_buffer_for_mono_segments;
1754   Buffer_for_vao<float> m_buffer_for_colored_segments;
1755   Buffer_for_vao<float> m_buffer_for_mono_rays;
1756   Buffer_for_vao<float> m_buffer_for_colored_rays;
1757   Buffer_for_vao<float> m_buffer_for_mono_lines;
1758   Buffer_for_vao<float> m_buffer_for_colored_lines;
1759   Buffer_for_vao<float> m_buffer_for_mono_faces;
1760   Buffer_for_vao<float> m_buffer_for_colored_faces;
1761   Buffer_for_vao<float> m_buffer_for_clipping_plane;
1762 
1763   static const unsigned int NB_VBO_BUFFERS=(END_POS-BEGIN_POS)+
1764     (END_COLOR-BEGIN_COLOR)+2; // +2 for 2 vectors of normals
1765 
1766   QGLBuffer buffers[NB_VBO_BUFFERS];
1767 
1768   // The following enum gives the indices of the differents vao.
1769   enum
1770     { VAO_MONO_POINTS=0,
1771       VAO_COLORED_POINTS,
1772       VAO_MONO_SEGMENTS,
1773       VAO_COLORED_SEGMENTS,
1774       VAO_MONO_RAYS,
1775       VAO_COLORED_RAYS,
1776       VAO_MONO_LINES,
1777       VAO_COLORED_LINES,
1778       VAO_MONO_FACES,
1779       VAO_COLORED_FACES,
1780       VAO_CLIPPING_PLANE,
1781       NB_VAO_BUFFERS
1782     };
1783   QOpenGLVertexArrayObject vao[NB_VAO_BUFFERS];
1784 
1785   QOpenGLShaderProgram rendering_program_face;
1786   QOpenGLShaderProgram rendering_program_p_l;
1787   QOpenGLShaderProgram rendering_program_clipping_plane;
1788 
1789   // variables for clipping plane
1790   bool clipping_plane_rendering = true; // will be toggled when alt+c is pressed, which is used for indicating whether or not to render the clipping plane ;
1791   float clipping_plane_rendering_transparency = 0.5f; // to what extent the transparent part should be rendered;
1792   float clipping_plane_rendering_size; // to what extent the size of clipping plane should be rendered;
1793 
1794   std::vector<std::tuple<Local_point, QString> > m_texts;
1795 };
1796 
1797 } // End namespace CGAL
1798 
1799 #else // CGAL_USE_BASIC_VIEWER
1800 
1801 namespace CGAL
1802 {
1803 
1804   template<class T>
1805   void draw(const T&, const char* ="", bool=false)
1806   {
1807     std::cerr<<"Impossible to draw, CGAL_USE_BASIC_VIEWER is not defined."<<std::endl;
1808   }
1809 
1810 } // End namespace CGAL
1811 
1812 #endif // CGAL_USE_BASIC_VIEWER
1813 
1814 #endif // CGAL_BASIC_VIEWER_QT_H
1815