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