1 #include <CGAL/Three/Scene_item_rendering_helper.h>
2 #include <QSlider>
3 #include <CGAL/Three/Viewer_interface.h>
4 #include <CGAL/Three/Triangle_container.h>
5 #include <CGAL/Three/Edge_container.h>
6 #include <CGAL/Three/Point_container.h>
7 #include <CGAL/Sqrt_extension.h>
8 #include <QWidgetAction>
9 #include <QMenu>
10 #include <QApplication>
11 #include <QThreadPool>
12 
13 using namespace CGAL::Three;
14 
15 struct PRIV{
PRIVPRIV16   PRIV(Scene_item_rendering_helper* item)
17     : item(item),
18       is_bbox_computed(false),
19       is_diag_bbox_computed(false),
20       _diag_bbox(0),
21       alphaSlider(nullptr),
22       are_buffers_filled(false)
23   {}
24 
~PRIVPRIV25   ~PRIV()
26   {
27     if(alphaSlider)
28       delete alphaSlider;
29 
30     for(std::size_t i = 0; i < triangle_containers.size(); ++i)
31     {
32       delete triangle_containers[i];
33     }
34     for(std::size_t i = 0; i < edge_containers.size(); ++i)
35     {
36       delete edge_containers[i];
37     }
38     for(std::size_t i = 0; i < point_containers.size(); ++i)
39     {
40       delete point_containers[i];
41     }
42   }
43 
44   Scene_item_rendering_helper* item;
45   Scene_item::Bbox _bbox;
46   bool is_bbox_computed;
47   bool is_diag_bbox_computed;
48   double _diag_bbox;
49   QSlider* alphaSlider;
50   bool are_buffers_filled;
51   std::map<CGAL::Three::Viewer_interface*, bool> isinit;
52   QMap<CGAL::Three::Viewer_interface*, bool> buffers_init;
53   std::vector<CGAL::Three::Triangle_container*> triangle_containers;
54   std::vector<CGAL::Three::Edge_container*> edge_containers;
55   std::vector<CGAL::Three::Point_container*> point_containers;
56 
57   void compute_diag_bbox();
58 };
59 
Scene_item_rendering_helper()60 Scene_item_rendering_helper::Scene_item_rendering_helper()
61   :Scene_item(0,0),
62     priv(new PRIV(this)){}
63 
~Scene_item_rendering_helper()64 Scene_item_rendering_helper::~Scene_item_rendering_helper()
65 {
66   if(priv)
67     delete priv;
68 }
69 
diagonalBbox() const70 double Scene_item_rendering_helper::diagonalBbox() const {
71   if(!priv->is_diag_bbox_computed)
72     priv->compute_diag_bbox();
73   priv->is_diag_bbox_computed = true;
74   return priv->_diag_bbox;
75 }
76 
compute_diag_bbox()77 void PRIV::compute_diag_bbox()
78 {
79   const Scene_item::Bbox& b_box = item->bbox();
80   _diag_bbox = CGAL::approximate_sqrt(
81           CGAL::square(b_box.xmax() - b_box.xmin())
82         + CGAL::square(b_box.ymax() - b_box.ymin())
83         + CGAL::square(b_box.zmax() - b_box.zmin())
84         );
85 }
86 
alpha() const87 float Scene_item_rendering_helper::alpha() const
88 {
89   if(!priv->alphaSlider)
90     return 1.0f;
91   return (float)priv->alphaSlider->value() / 255.0f;
92 }
93 
initGL(CGAL::Three::Viewer_interface * viewer) const94 void Scene_item_rendering_helper::initGL(CGAL::Three::Viewer_interface* viewer) const
95 {
96   if(!priv->alphaSlider)
97   {
98     priv->alphaSlider = new QSlider(::Qt::Horizontal);
99     priv->alphaSlider->setMinimum(0);
100     priv->alphaSlider->setMaximum(255);
101     priv->alphaSlider->setValue(255);
102   }
103 
104   Q_FOREACH(Triangle_container* tc, priv->triangle_containers)
105   {
106     if(!tc->isGLInit(viewer))
107       tc->initGL(viewer);
108   }
109   Q_FOREACH(Edge_container* ec, priv->edge_containers)
110   {
111     if(!ec->isGLInit(viewer))
112       ec->initGL(viewer);
113   }
114   Q_FOREACH(Point_container* pc, priv->point_containers)
115   {
116     if(!pc->isGLInit(viewer))
117       pc->initGL(viewer);
118   }
119   if(!getBuffersFilled())
120   {
121     Gl_data_names flags;
122     flags = (ALL);
123     processData(flags);
124   }
125   priv->isinit[viewer] = true;
126 }
127 
processData(Gl_data_names) const128 void Scene_item_rendering_helper::processData(Gl_data_names )const
129 {
130   computeElements();
131   priv->are_buffers_filled = true;
132 }
133 
134 
contextMenu()135 QMenu* Scene_item_rendering_helper::contextMenu()
136 {
137   QMenu* resMenu = Scene_item::contextMenu();
138   bool prop = property("menu_changed").toBool();
139   if(!prop)
140   {
141     QMenu *container = new QMenu(tr("Alpha value"));
142     QWidgetAction *sliderAction = new QWidgetAction(nullptr);
143 
144     sliderAction->setDefaultWidget(priv->alphaSlider);
145     container->addAction(sliderAction);
146     resMenu->addMenu(container);
147     setProperty("menu_changed", true);
148   }
149   return resMenu;
150 }
151 
setAlpha(int alpha)152 void Scene_item_rendering_helper::setAlpha(int alpha)
153 {
154   if(!priv->alphaSlider)
155   {
156     priv->alphaSlider = new QSlider(::Qt::Horizontal);
157     priv->alphaSlider->setMinimum(0);
158     priv->alphaSlider->setMaximum(255);
159     priv->alphaSlider->setValue(255);
160   }
161   priv->alphaSlider->setValue(alpha);
162   redraw();
163 }
164 
bbox() const165 Scene_item::Bbox Scene_item_rendering_helper::bbox() const {
166   if(!priv->is_bbox_computed)
167     compute_bbox();
168   priv->is_bbox_computed = true;
169   return priv->_bbox;
170 }
171 
isInit(CGAL::Three::Viewer_interface * viewer) const172 bool Scene_item_rendering_helper::isInit(CGAL::Three::Viewer_interface* viewer)const
173 {
174   if(priv->isinit.find(viewer) != priv->isinit.end())
175     return priv->isinit[viewer];
176   return false;
177 }
178 
alphaSlider()179 QSlider* Scene_item_rendering_helper::alphaSlider() { return priv->alphaSlider; }
180 
setBbox(Bbox b) const181 void Scene_item_rendering_helper::setBbox(Bbox b)const { priv->_bbox = b; }
182 
getTriangleContainer(std::size_t id) const183 Triangle_container* Scene_item_rendering_helper::getTriangleContainer(std::size_t id)const
184 {
185   return priv->triangle_containers[id];
186 }
187 
getEdgeContainer(std::size_t id) const188 Edge_container* Scene_item_rendering_helper::getEdgeContainer(std::size_t id)const
189 {
190   return priv->edge_containers[id];
191 }
192 
getPointContainer(std::size_t id) const193 Point_container* Scene_item_rendering_helper::getPointContainer(std::size_t id)const
194 {
195   return priv->point_containers[id];
196 }
197 
198 
setTriangleContainer(std::size_t id,Triangle_container * tc)199 void Scene_item_rendering_helper::setTriangleContainer(std::size_t id,
200                                                        Triangle_container* tc)
201 {
202   if(priv->triangle_containers.size() <= id)
203   {
204     priv->triangle_containers.resize(id+1, nullptr);
205   }
206   if(priv->triangle_containers[id])
207     delete priv->triangle_containers[id];
208   priv->triangle_containers[id] = tc;
209 }
210 
setEdgeContainer(std::size_t id,Edge_container * ec)211 void Scene_item_rendering_helper::setEdgeContainer(std::size_t id,
212                                                    Edge_container* ec)
213 {
214   if(priv->edge_containers.size() <= id)
215   {
216     priv->edge_containers.resize(id+1, nullptr);
217   }
218   if(priv->edge_containers[id])
219     delete priv->edge_containers[id];
220   priv->edge_containers[id] = ec;
221 }
222 
setPointContainer(std::size_t id,Point_container * pc)223 void Scene_item_rendering_helper::setPointContainer(std::size_t id,
224                                                    Point_container* pc)
225 {
226   if(priv->point_containers.size() <= id)
227   {
228     priv->point_containers.resize(id+1, nullptr);
229   }
230   if(priv->point_containers[id])
231     delete priv->point_containers[id];
232   priv->point_containers[id] = pc;
233 }
234 
235 
setBuffersFilled(bool b) const236 void Scene_item_rendering_helper::setBuffersFilled(bool b) const
237 {
238   priv->are_buffers_filled = b;
239 }
240 
getBuffersFilled() const241 bool Scene_item_rendering_helper::getBuffersFilled()const
242 {
243   return priv->are_buffers_filled;
244 }
245 
getBuffersInit(Viewer_interface * viewer) const246 bool Scene_item_rendering_helper::getBuffersInit(Viewer_interface* viewer) const
247 {
248   return priv->buffers_init[viewer];
249 }
250 
setBuffersInit(Viewer_interface * viewer,bool val) const251 void Scene_item_rendering_helper::setBuffersInit(Viewer_interface* viewer, bool val)const
252 {
253   priv->buffers_init[viewer] = val;
254 }
255 
removeViewer(Viewer_interface * viewer)256 void Scene_item_rendering_helper::removeViewer(Viewer_interface *viewer)
257 {
258   Q_FOREACH(Triangle_container* tc, priv->triangle_containers)
259   {
260     tc->removeViewer(viewer);
261   }
262   Q_FOREACH(Edge_container* ec, priv->edge_containers)
263   {
264     ec->removeViewer(viewer);
265   }
266   Q_FOREACH(Point_container* pc, priv->point_containers)
267   {
268     pc->removeViewer(viewer);
269   }
270 }
271 
newViewer(Viewer_interface * viewer)272 void Scene_item_rendering_helper::newViewer(Viewer_interface *viewer)
273 {
274   viewer->makeCurrent();
275   Q_FOREACH(Triangle_container* tc, priv->triangle_containers)
276   {
277     if(!tc->isGLInit(viewer))
278       tc->initGL(viewer);
279   }
280   Q_FOREACH(Edge_container* ec, priv->edge_containers)
281   {
282     if(!ec->isGLInit(viewer))
283       ec->initGL(viewer);
284   }
285   Q_FOREACH(Point_container* pc, priv->point_containers)
286   {
287     if(!pc->isGLInit(viewer))
288       pc->initGL(viewer);
289   }
290   //call function that recomputes vao binding
291   initializeBuffers(viewer);
292 }
293