DGtal  1.2.0
Viewer3D.ih
1 /**
2  * This program is free software: you can redistribute it and/or modify
3  * it under the terms of the GNU Lesser General Public License as
4  * published by the Free Software Foundation, either version 3 of the
5  * License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESSpace FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program. If not, see <http://www.gnu.org/licenses/>.
14  *
15  **/
16 
17 /**
18  * @file Viewer3D.ih
19  * @author Bertrand Kerautret (\c kerautre@loria.fr )
20  * LORIA (CNRS, UMR 7503), University of Nancy, France
21  *
22  * @date 2011/01/03
23  *
24  * Implementation of inline methods defined in Viewer3D.h
25  *
26  * This file is part of the DGtal library.
27  */
28 
29 ///////////////////////////////////////////////////////////////////////////////
30 // IMPLEMENTATION of inline methods.
31 ///////////////////////////////////////////////////////////////////////////////
32 
33 //////////////////////////////////////////////////////////////////////////////
34 #ifdef _MSC_VER
35 #define NOMINMAX
36 #include <windows.h>
37 #include <GL/gl.h>
38 #include "DGtal/io/viewers/windows/GL/glext.h"
39 #endif
40 
41 #include "DGtal/io/viewers/Viewer3D.h"
42 
43 #include <algorithm>
44 #include <limits>
45 #include <QColor>
46 #include <QTextEdit>
47 #include <QMessageBox>
48 #include <QTextStream>
49 #include <QDir>
50 
51 #include <cstdlib>
52 #include "DGtal/io/CDrawableWithDisplay3D.h"
53 #include "DGtal/io/viewers/CDrawableWithViewer3D.h"
54 #include "DGtal/io/viewers/Viewer3DFactory.h"
55 #include "QGLViewer/manipulatedFrame.h"
56 #include "QGLViewer/manipulatedCameraFrame.h"
57 //////////////////////////////////////////////////////////////////////////////
58 
59 using namespace qglviewer;
60 
61 ///////////////////////////////////////////////////////////////////////////////
62 // Implementation of inline methods //
63 
64 template <typename TSpace, typename TKSpace>
65 inline void DGtal::Viewer3D<TSpace, TKSpace>::rotateDomain(
66 Image2DDomainD3D & anDom, double angleRotation, ImageDirection rotationDir )
67 {
68  DGtal::PointVector<3, int> pt;
69  pt[0] = (int) (anDom.point1[0]+anDom.point2[0]+anDom.point3[0]+anDom.point4[0])/4.0;
70  pt[1] = (int) (anDom.point1[1]+anDom.point2[1]+anDom.point3[1]+anDom.point4[1])/4.0;
71  pt[2] = (int) (anDom.point1[2]+anDom.point2[2]+anDom.point3[2]+anDom.point4[2])/4.0;
72  rotateImageVertex(anDom, angleRotation, rotationDir);
73 
74  std::vector<typename DGtal::Display3D<TSpace, TKSpace>::LineD3D> & aVectLine =
75  Viewer3D<TSpace, TKSpace>::myLineSetList.at( anDom.myLineSetIndex );
76  for(unsigned int i = 0; i< aVectLine.size();i++){
77  typename DGtal::Display3D<TSpace, TKSpace>::LineD3D & aLine =
78  aVectLine.at( i );
79  rotateLineD3D(aLine, pt, angleRotation, rotationDir );
80  }
81 
82 }
83 
84 template <typename TSpace, typename TKSpace>
85 template <typename TValues>
86 inline void DGtal::Viewer3D<TSpace, TKSpace>::rotatePoint(
87 TValues & x, TValues & y, TValues & z, double cx, double cy, double cz,
88 double angleRotation, ImageDirection rotationDir )
89 {
90  double dx = x-cx; double dy = y-cy; double dz = z-cz;
91  if(rotationDir == zDirection){
92  x = cx+dx*cos(angleRotation)-dy*sin(angleRotation);
93  y = cy+dx*sin(angleRotation)+dy*cos(angleRotation);
94  }
95  if(rotationDir == yDirection){
96  x = cx+dx*cos(angleRotation)-dz*sin(angleRotation);
97  z = cz+dx*sin(angleRotation)+dz*cos(angleRotation);
98  }
99  if(rotationDir == xDirection){
100  y = cy+dy*cos(angleRotation)-dz*sin(angleRotation);
101  z = cz+dy*sin(angleRotation)+dz*cos(angleRotation);
102  }
103 }
104 
105 template <typename TSpace, typename TKSpace>
106 template <typename TContainer>
107 inline void DGtal::Viewer3D<TSpace, TKSpace>::rotateLineD3D(
108 typename DGtal::Display3D<TSpace, TKSpace>::LineD3D & aLine,
109 DGtal::PointVector<3, int, TContainer> pt, double angleRotation,
110 ImageDirection dirRotation )
111 {
112  double dx1 = aLine.point1[0] - pt[0]; double dy1 = aLine.point1[1] - pt[1]; double dz1 = aLine.point1[2] - pt[2];
113  double dx2 = aLine.point2[0] - pt[0]; double dy2 = aLine.point2[1] - pt[1]; double dz2 = aLine.point2[2] - pt[2];
114  if(dirRotation==zDirection){
115  aLine.point1[0]=pt[0]+dx1*std::cos(angleRotation)-dy1*std::sin(angleRotation);
116  aLine.point1[1]=pt[1]+dx1*std::sin(angleRotation)+dy1*std::cos(angleRotation);
117 
118  aLine.point2[0]=pt[0]+dx2*std::cos(angleRotation)-dy2*std::sin(angleRotation);
119  aLine.point2[1]=pt[1]+dx2*std::sin(angleRotation)+dy2*std::cos(angleRotation);
120 
121  }else if(dirRotation==xDirection){
122  aLine.point1[1]=pt[1]+dy1*std::cos(angleRotation)-dz1*std::sin(angleRotation);
123  aLine.point1[2]=pt[2]+dy1*std::sin(angleRotation)+dz1*std::cos(angleRotation);
124 
125  aLine.point2[1]=pt[1]+dy2*std::cos(angleRotation)-dz2*std::sin(angleRotation);
126  aLine.point2[2]=pt[2]+dy2*std::sin(angleRotation)+dz2*std::cos(angleRotation);
127  }else if(dirRotation==yDirection){
128  aLine.point1[0]=pt[0]+dx1*std::cos(angleRotation)-dz1*std::sin(angleRotation);
129  aLine.point1[2]=pt[2]+dx1*std::sin(angleRotation)+dz1*std::cos(angleRotation);
130 
131  aLine.point2[0]=pt[0]+dx2*std::cos(angleRotation)-dz2*std::sin(angleRotation);
132  aLine.point2[2]=pt[2]+dx2*std::sin(angleRotation)+dz2*std::cos(angleRotation);
133  }else{
134  trace.error() << "No direction!!"<< std::endl;
135  }
136 
137 }
138 
139 template <typename TSpace, typename TKSpace>
140 inline unsigned int DGtal::Viewer3D<TSpace, TKSpace>::getCurrentDomainNumber()
141 {
142  return static_cast<unsigned int>(myImageDomainList.size());
143 }
144 
145 template <typename TSpace, typename TKSpace>
146 inline unsigned int DGtal::Viewer3D<TSpace, TKSpace>::getCurrentGLImageNumber()
147 {
148  return static_cast<unsigned int>(myGSImageList.size());
149 }
150 
151 template <typename TSpace, typename TKSpace>
152 inline void DGtal::Viewer3D<TSpace, TKSpace>::addTextureImage(
153 const typename Viewer3D<TSpace, TKSpace>::TextureImage & image )
154 {
155  myGSImageList.push_back(image);
156  Display3D<TSpace, TKSpace>::updateBoundingBox( image.point1 );
157  Display3D<TSpace, TKSpace>::updateBoundingBox( image.point2 );
158  Display3D<TSpace, TKSpace>::updateBoundingBox( image.point3 );
159  Display3D<TSpace, TKSpace>::updateBoundingBox( image.point4 );
160 }
161 
162 template <typename TSpace, typename TKSpace>
163 template <typename TImageType, typename TFunctor>
164 inline void DGtal::Viewer3D<TSpace, TKSpace>::updateTextureImage(
165 unsigned int imageIndex, const TImageType & image, const TFunctor & aFunctor,
166 double xTranslation, double yTranslation, double zTranslation,
167 double rotationAngle, ImageDirection rotationDir )
168 {
169  BOOST_CONCEPT_ASSERT(( concepts::CConstImage < TImageType > ));
170  assert ( imageIndex< myGSImageList.size());
171  typename Viewer3D<TSpace, TKSpace>::TextureImage & anImage =
172  myGSImageList.at( imageIndex );
173  Display::updateBoundingBox(RealPoint(anImage.point1[0]+xTranslation,
174  anImage.point1[1]+yTranslation,
175  anImage.point1[2]+zTranslation));
176  Display::updateBoundingBox(RealPoint(anImage.point2[0]+xTranslation,
177  anImage.point2[1]+yTranslation,
178  anImage.point2[2]+zTranslation));
179  Display::updateBoundingBox(RealPoint(anImage.point3[0]+xTranslation,
180  anImage.point3[1]+yTranslation,
181  anImage.point3[2]+zTranslation));
182  Display::updateBoundingBox(RealPoint(anImage.point4[0]+xTranslation,
183  anImage.point4[1]+yTranslation,
184  anImage.point4[2]+zTranslation));
185  anImage.updateImageDataAndParam(image, aFunctor, xTranslation, yTranslation, zTranslation);
186  if(anImage.myDrawDomain)
187  {
188  *this << DGtal::Translate2DDomain(anImage.myIndexDomain, xTranslation, yTranslation, zTranslation);
189  }
190 
191  if(rotationAngle!=0.0){
192  rotateDomain(myImageDomainList.at(anImage.myIndexDomain), rotationAngle, rotationDir);
193  rotateImageVertex(anImage, rotationAngle, rotationDir);
194  }
195 }
196 
197 template <typename TSpace, typename TKSpace>
198 inline void DGtal::Viewer3D<TSpace, TKSpace>::updateOrientationTextureImage(
199 unsigned int imageIndex, double xPosition, double yPosition, double zPosition,
200 ImageDirection newDirection )
201 {
202  assert ( imageIndex< myGSImageList.size());
203  typename Viewer3D<TSpace, TKSpace>::TextureImage & anImage =
204  myGSImageList.at( imageIndex );
205  Display3D<TSpace, TKSpace>::updateBoundingBox( anImage.point1 );
206  Display3D<TSpace, TKSpace>::updateBoundingBox( anImage.point2 );
207  Display3D<TSpace, TKSpace>::updateBoundingBox( anImage.point3 );
208  Display3D<TSpace, TKSpace>::updateBoundingBox( anImage.point4 );
209  anImage.updateImageOrientation(newDirection, xPosition, yPosition, zPosition);
210  if(anImage.myDrawDomain)
211  {
212  *this << DGtal::Update2DDomainPosition<Space ,KSpace >(anImage.myIndexDomain,
213  newDirection,
214  xPosition,
215  yPosition, zPosition);
216  }
217 }
218 
219 template <typename TSpace, typename TKSpace>
220 inline void DGtal::Viewer3D<TSpace, TKSpace>::updateEmbeddingTextureImage(
221 unsigned int anImageIndex, typename Space::Point aPoint1,
222 typename Space::Point aPoint2, typename Space::Point aPoint3,
223 typename Space::Point aPoint4 )
224 {
225  assert ( anImageIndex< myGSImageList.size());
226  typename Viewer3D<TSpace, TKSpace>::TextureImage & anImage =
227  myGSImageList.at( anImageIndex );
228  Display3D<TSpace, TKSpace>::updateBoundingBox( aPoint1 );
229  Display3D<TSpace, TKSpace>::updateBoundingBox( aPoint2 );
230  Display3D<TSpace, TKSpace>::updateBoundingBox( aPoint3 );
231  Display3D<TSpace, TKSpace>::updateBoundingBox( aPoint4 );
232  anImage.updateImage3DEmbedding(aPoint1, aPoint2, aPoint3, aPoint4);
233 }
234 
235 template <typename TSpace, typename TKSpace>
236 inline void
237 DGtal::Viewer3D<TSpace, TKSpace>::TextureImage::updateImageOrientation(
238 ImageDirection normalDir, double xBottomLeft, double yBottomLeft,
239 double zBottomLeft )
240 {
241  if(normalDir==zDirection)
242  {
243  point1[0] = xBottomLeft-0.5; point1[1] = yBottomLeft-0.5; point1[2] = zBottomLeft;
244  point2[0] = xBottomLeft+myImageWidth-0.5; point2[1] = yBottomLeft-0.5; point2[2] = zBottomLeft;
245  point3[0] = xBottomLeft+myImageWidth-0.5; point3[1] = yBottomLeft+myImageHeight-0.5; point3[2] = zBottomLeft;
246  point4[0] = xBottomLeft-0.5; point4[1] = yBottomLeft+myImageHeight-0.5; point4[2] = zBottomLeft;
247  }else if(normalDir==yDirection)
248  {
249  point1[0] = xBottomLeft-0.5; point1[1] = yBottomLeft; point1[2] = zBottomLeft-0.5;
250  point2[0] = xBottomLeft+myImageWidth-0.5; point2[1] = yBottomLeft; point2[2] = zBottomLeft-0.5;
251  point3[0] = xBottomLeft+myImageWidth-0.5; point3[1] = yBottomLeft; point3[2] = zBottomLeft+myImageHeight-0.5;
252  point4[0] = xBottomLeft-0.5; point4[1] = yBottomLeft; point4[2] = zBottomLeft+myImageHeight-0.5;
253  }else if(normalDir==xDirection)
254  {
255  point1[0] = xBottomLeft; point1[1] = yBottomLeft-0.5; point1[2]= zBottomLeft-0.5;
256  point2[0] = xBottomLeft; point2[1] = yBottomLeft+myImageWidth-0.5; point2[2] = zBottomLeft-0.5;
257  point3[0] = xBottomLeft; point3[1] = yBottomLeft+myImageWidth-0.5; point3[2] = zBottomLeft+myImageHeight-0.5;
258  point4[0] = xBottomLeft; point4[1] = yBottomLeft-0.5; point4[2] = zBottomLeft+myImageHeight-0.5;
259  }
260  myDirection=normalDir;
261 }
262 
263 template <typename TSpace, typename TKSpace>
264 inline void
265 DGtal::Viewer3D<TSpace, TKSpace>::Image2DDomainD3D::updateDomainOrientation(
266 ImageDirection normalDir, double xBottomLeft, double yBottomLeft,
267 double zBottomLeft )
268 {
269  if(normalDir==zDirection)
270  {
271  point1[0] = xBottomLeft-0.5; point1[1] = yBottomLeft-0.5; point1[2] = zBottomLeft;
272  point2[0] = xBottomLeft+myDomainWidth-0.5; point2[1] = yBottomLeft-0.5; point2[2] = zBottomLeft;
273  point3[0] = xBottomLeft+myDomainWidth-0.5; point3[1] = yBottomLeft+myDomainHeight-0.5; point3[2] = zBottomLeft;
274  point4[0] = xBottomLeft-0.5; point4[1] = yBottomLeft+myDomainHeight-0.5; point4[2] = zBottomLeft;
275  }else if(normalDir==yDirection)
276  {
277  point1[0] = xBottomLeft-0.5; point1[1] = yBottomLeft; point1[2] = zBottomLeft-0.5;
278  point2[0] = xBottomLeft+myDomainWidth-0.5; point2[1] = yBottomLeft; point2[2] = zBottomLeft-0.5;
279  point3[0] = xBottomLeft+myDomainWidth-0.5; point3[1] = yBottomLeft; point3[2] = zBottomLeft+myDomainHeight-0.5;
280  point4[0] = xBottomLeft-0.5; point4[1] = yBottomLeft; point4[2] = zBottomLeft+myDomainHeight-0.5;
281  }else if(normalDir==xDirection)
282  {
283  point1[0] = xBottomLeft; point1[1] = yBottomLeft-0.5; point1[2]= zBottomLeft-0.5;
284  point2[0] = xBottomLeft; point2[1] = yBottomLeft+myDomainWidth-0.5; point2[2] = zBottomLeft-0.5;
285  point3[0] = xBottomLeft; point3[1] = yBottomLeft+myDomainWidth-0.5; point3[2] = zBottomLeft+myDomainHeight-0.5;
286  point4[0] = xBottomLeft; point4[1] = yBottomLeft-0.5; point4[2] = zBottomLeft+myDomainHeight-0.5;
287  }
288  myDirection=normalDir;
289 }
290 
291 template <typename TSpace, typename TKSpace>
292 inline void DGtal::Viewer3D<TSpace, TKSpace>::Image2DDomainD3D::translateDomain(
293 double xTranslation, double yTranslation, double zTranslation )
294 {
295  point1[0] += xTranslation; point1[1] += yTranslation; point1[2] += zTranslation;
296  point2[0] += xTranslation; point2[1] += yTranslation; point2[2] += zTranslation;
297  point3[0] += xTranslation; point3[1] += yTranslation; point3[2] += zTranslation;
298  point4[0] += xTranslation; point4[1] += yTranslation; point4[2] += zTranslation;
299 }
300 
301 template <typename TSpace, typename TKSpace>
302 template <typename TDomain>
303 void DGtal::Viewer3D<TSpace, TKSpace>::addImage2DDomainD3D(
304 const TDomain & aDomain, std::string mode, const DGtal::Color & aColor )
305 {
306  typename DGtal::Viewer3D<TSpace, TKSpace>::Image2DDomainD3D anImageDomain(
307  aDomain );
308  anImageDomain.color = aColor;
309  anImageDomain.myMode = mode;
310  anImageDomain.myLineSetIndex =
311  Viewer3D<TSpace, TKSpace>::myLineSetList.size();
312 
313  myImageDomainList.push_back(anImageDomain);
314  Display3D<TSpace, TKSpace>::updateBoundingBox( anImageDomain.point1 );
315  Display3D<TSpace, TKSpace>::updateBoundingBox( anImageDomain.point2 );
316  Display3D<TSpace, TKSpace>::updateBoundingBox( anImageDomain.point3 );
317  Display3D<TSpace, TKSpace>::updateBoundingBox( anImageDomain.point4 );
318 
319  std::vector<typename DGtal::Viewer3D<TSpace, TKSpace>::LineD3D> vectLines =
320  compute2DDomainLineRepresentation( anImageDomain );
321  Viewer3D<TSpace, TKSpace>::myLineSetList.push_back( vectLines );
322 }
323 
324 template <typename TSpace, typename TKSpace>
325 inline std::vector<typename DGtal::Viewer3D<TSpace, TKSpace>::LineD3D>
326 DGtal::Viewer3D<TSpace, TKSpace>::compute2DDomainLineRepresentation(
327 typename DGtal::Viewer3D<TSpace, TKSpace>::Image2DDomainD3D & anImageDomain )
328 {
329  std::vector<typename DGtal::Viewer3D<TSpace, TKSpace>::LineD3D>
330  vectLinesResu = compute2DDomainLineRepresentation( anImageDomain, 0.05 );
331  std::vector<typename DGtal::Viewer3D<TSpace, TKSpace>::LineD3D>
332  vectLinesVerso = compute2DDomainLineRepresentation( anImageDomain, -0.05 );
333  for(unsigned int i=0; i<vectLinesVerso.size(); i++)
334  {
335  vectLinesResu.push_back(vectLinesVerso.at(i));
336  }
337  return vectLinesResu;
338 }
339 
340 template <typename TSpace, typename TKSpace>
341 inline std::vector<typename DGtal::Viewer3D<TSpace, TKSpace>::LineD3D>
342 DGtal::Viewer3D<TSpace, TKSpace>::compute2DDomainLineRepresentation(
343 typename DGtal::Viewer3D<TSpace, TKSpace>::Image2DDomainD3D & anImageDomain,
344 double delta )
345 {
346  std::vector<typename DGtal::Viewer3D<TSpace, TKSpace>::LineD3D> aLineSet;
347  typename Viewer3D<TSpace, TKSpace>::LineD3D aLine;
348  aLine.color = anImageDomain.color;
349  aLine.width=0.1;
350 
351  if( anImageDomain.myMode=="BoundingBox")
352  {
353  aLine.point1[0]=anImageDomain.point1[0]; aLine.point1[1]=anImageDomain.point1[1]; aLine.point1[2]=anImageDomain.point1[2];
354  aLine.point2[0]=anImageDomain.point2[0]; aLine.point2[1]=anImageDomain.point2[1]; aLine.point2[2]=anImageDomain.point2[2];
355  aLineSet.push_back(aLine);
356  aLine.point1[0]=anImageDomain.point2[0]; aLine.point1[1]=anImageDomain.point2[1]; aLine.point1[2]=anImageDomain.point2[2];
357  aLine.point2[0]=anImageDomain.point3[0]; aLine.point2[1]=anImageDomain.point3[1]; aLine.point2[2]=anImageDomain.point3[2];
358  aLineSet.push_back(aLine);
359  aLine.point1[0]=anImageDomain.point3[0]; aLine.point1[1]=anImageDomain.point3[1]; aLine.point1[2]=anImageDomain.point3[2];
360  aLine.point2[0]=anImageDomain.point4[0]; aLine.point2[1]=anImageDomain.point4[1]; aLine.point2[2]=anImageDomain.point4[2];
361  aLineSet.push_back(aLine);
362  aLine.point1[0]=anImageDomain.point4[0]; aLine.point1[1]=anImageDomain.point4[1]; aLine.point1[2]=anImageDomain.point4[2];
363  aLine.point2[0]=anImageDomain.point1[0]; aLine.point2[1]=anImageDomain.point1[1]; aLine.point2[2]=anImageDomain.point1[2];
364  aLineSet.push_back(aLine);
365  }else if(anImageDomain.myMode=="InterGrid")
366  {
367  if(anImageDomain.myDirection==zDirection)
368  {
369  //lines align to the x direction
370  for(unsigned int i=0; i <= anImageDomain.myDomainHeight; i++)
371  {
372  aLine.point1[0] = anImageDomain.point1[0]; aLine.point1[1] = anImageDomain.point1[1]+i; aLine.point1[2] = anImageDomain.point1[2]+delta;
373  aLine.point2[0] = anImageDomain.point2[0]; aLine.point2[1] = anImageDomain.point2[1]+i; aLine.point2[2] = anImageDomain.point2[2]+delta;
374  aLineSet.push_back(aLine);
375  }
376  //lines align to the y direction
377  for(unsigned int i=0; i <= anImageDomain.myDomainWidth; i++)
378  {
379  aLine.point1[0] = anImageDomain.point1[0]+i; aLine.point1[1] = anImageDomain.point1[1]; aLine.point1[2] = anImageDomain.point1[2]+delta;
380  aLine.point2[0] = anImageDomain.point4[0]+i; aLine.point2[1] = anImageDomain.point4[1]; aLine.point2[2] = anImageDomain.point4[2]+delta;
381  aLineSet.push_back(aLine);
382  }
383  }else if(anImageDomain.myDirection==xDirection)
384  {
385  //lines align to the y direction
386  for(unsigned int i=0; i <= anImageDomain.myDomainHeight; i++)
387  {
388  aLine.point1[0] = anImageDomain.point1[0]+delta; aLine.point1[1] = anImageDomain.point1[1]; aLine.point1[2] = anImageDomain.point1[2]+i;
389  aLine.point2[0] = anImageDomain.point1[0]+delta; aLine.point2[1] = anImageDomain.point2[1]; aLine.point2[2] = anImageDomain.point1[2]+i;
390  aLineSet.push_back(aLine);
391  }
392 
393  //lines align to the z direction
394  for(unsigned int i=0; i <= anImageDomain.myDomainWidth; i++)
395  {
396  aLine.point1[0] = anImageDomain.point1[0]+delta; aLine.point1[1] = anImageDomain.point1[1]+i; aLine.point1[2] = anImageDomain.point1[2];
397  aLine.point2[0] = anImageDomain.point1[0]+delta; aLine.point2[1] = anImageDomain.point1[1]+i; aLine.point2[2] = anImageDomain.point4[2];
398  aLineSet.push_back(aLine);
399  }
400  }else if(anImageDomain.myDirection==yDirection)
401  {
402  //lines align to the x direction
403  for(unsigned int i=0; i <= anImageDomain.myDomainHeight; i++)
404  {
405  aLine.point1[0] = anImageDomain.point1[0]; aLine.point1[1] = anImageDomain.point1[1]+delta; aLine.point1[2] = anImageDomain.point1[2]+i;
406  aLine.point2[0] = anImageDomain.point2[0]; aLine.point2[1] = anImageDomain.point1[1]+delta; aLine.point2[2] = anImageDomain.point1[2]+i;
407  aLineSet.push_back(aLine);
408  }
409 
410  //lines align to the z direction
411  for(unsigned int i=0; i <= anImageDomain.myDomainWidth; i++)
412  {
413  aLine.point1[0] = anImageDomain.point1[0]+i; aLine.point1[1] = anImageDomain.point1[1]+delta; aLine.point1[2] = anImageDomain.point1[2];
414  aLine.point2[0] = anImageDomain.point1[0]+i; aLine.point2[1] = anImageDomain.point1[1]+delta; aLine.point2[2] = anImageDomain.point4[2];
415  aLineSet.push_back(aLine);
416  }
417  }
418  }else if(anImageDomain.myMode=="Grid")
419  {
420  if(anImageDomain.myDirection==zDirection)
421  {
422  //lines align to the x direction
423  for(unsigned int i=0; i < anImageDomain.myDomainHeight; i++)
424  {
425  aLine.point1[0] = anImageDomain.point1[0]; aLine.point1[1] = anImageDomain.point1[1]+i+0.5; aLine.point1[2] = anImageDomain.point1[2]+delta;
426  aLine.point2[0] = anImageDomain.point2[0]; aLine.point2[1] = anImageDomain.point2[1]+i+0.5; aLine.point2[2] = anImageDomain.point2[2]+delta;
427  aLineSet.push_back(aLine);
428  }
429  //lines align to the y direction
430  for(unsigned int i=0; i < anImageDomain.myDomainWidth; i++)
431  {
432  aLine.point1[0] = anImageDomain.point1[0]+i+0.5; aLine.point1[1] = anImageDomain.point1[1]; aLine.point1[2] = anImageDomain.point1[2]+delta;
433  aLine.point2[0] = anImageDomain.point4[0]+i+0.5; aLine.point2[1] = anImageDomain.point4[1]; aLine.point2[2] = anImageDomain.point4[2]+delta;
434  aLineSet.push_back(aLine);
435  }
436  }else if(anImageDomain.myDirection==xDirection)
437  {
438  //lines align to the y direction
439  for(unsigned int i=0; i < anImageDomain.myDomainHeight; i++)
440  {
441  aLine.point1[0] = anImageDomain.point1[0]+delta; aLine.point1[1] = anImageDomain.point1[1]; aLine.point1[2] = anImageDomain.point1[2]+i+0.5;
442  aLine.point2[0] = anImageDomain.point1[0]+delta; aLine.point2[1] = anImageDomain.point2[1]; aLine.point2[2] = anImageDomain.point1[2]+i+0.5;
443  aLineSet.push_back(aLine);
444  }
445 
446  //lines align to the z direction
447  for(unsigned int i=0; i < anImageDomain.myDomainWidth; i++)
448  {
449  aLine.point1[0] = anImageDomain.point1[0]+delta; aLine.point1[1] = anImageDomain.point1[1]+i+0.5; aLine.point1[2] = anImageDomain.point1[2];
450  aLine.point2[0] = anImageDomain.point1[0]+delta; aLine.point2[1] = anImageDomain.point1[1]+i+0.5; aLine.point2[2] = anImageDomain.point4[2];
451  aLineSet.push_back(aLine);
452  }
453  }else if(anImageDomain.myDirection==yDirection)
454  {
455  //lines align to the x direction
456  for(unsigned int i=0; i < anImageDomain.myDomainHeight; i++)
457  {
458  aLine.point1[0] = anImageDomain.point1[0]; aLine.point1[1] = anImageDomain.point1[1]+delta; aLine.point1[2] = anImageDomain.point1[2]+i+0.5;
459  aLine.point2[0] = anImageDomain.point2[0]; aLine.point2[1] = anImageDomain.point1[1]+delta; aLine.point2[2] = anImageDomain.point1[2]+i+0.5;
460  aLineSet.push_back(aLine);
461  }
462 
463  //lines align to the z direction
464  for(unsigned int i=0; i < anImageDomain.myDomainWidth; i++)
465  {
466  aLine.point1[0] = anImageDomain.point1[0]+i+0.5; aLine.point1[1] = anImageDomain.point1[1]+delta; aLine.point1[2] = anImageDomain.point1[2];
467  aLine.point2[0] = anImageDomain.point1[0]+i+0.5; aLine.point2[1] = anImageDomain.point1[1]+delta; aLine.point2[2] = anImageDomain.point4[2];
468  aLineSet.push_back(aLine);
469  }
470  }
471  }
472  return aLineSet;
473 }
474 
475 template <typename TSpace, typename TKSpace>
476 inline void DGtal::Viewer3D<TSpace, TKSpace>::updateAn2DDomainOrientation(
477 unsigned int domainIndex, double xPosition, double yPosition, double zPosition,
478 ImageDirection newDirection )
479 {
480  ASSERT( domainIndex < myImageDomainList.size());
481  typename Viewer3D<TSpace, TKSpace>::Image2DDomainD3D & aDomain =
482  myImageDomainList.at( domainIndex );
483 
484  Display3D<TSpace, TKSpace>::updateBoundingBox( aDomain.point1 );
485  Display3D<TSpace, TKSpace>::updateBoundingBox( aDomain.point2 );
486  Display3D<TSpace, TKSpace>::updateBoundingBox( aDomain.point3 );
487  Display3D<TSpace, TKSpace>::updateBoundingBox( aDomain.point4 );
488  aDomain.updateDomainOrientation(newDirection, xPosition, yPosition, zPosition);
489 
490  std::vector<typename DGtal::Viewer3D<TSpace, TKSpace>::LineD3D> vectNewLines =
491  compute2DDomainLineRepresentation( aDomain );
492  std::vector<typename DGtal::Viewer3D<TSpace, TKSpace>::LineD3D> & vectLines =
493  Viewer3D<TSpace, TKSpace>::myLineSetList.at( aDomain.myLineSetIndex );
494  vectLines.clear();
495  for(unsigned int i=0; i<vectNewLines.size(); i++)
496  {
497  vectLines.push_back(vectNewLines.at(i));
498  }
499 
500 }
501 
502 template <typename TSpace, typename TKSpace>
503 inline void DGtal::Viewer3D<TSpace, TKSpace>::translateAn2DDomain(
504 unsigned int domainIndex, double xTranslation, double yTranslation,
505 double zTranslation )
506 {
507  typename Viewer3D<TSpace, TKSpace>::Image2DDomainD3D & anDomain =
508  myImageDomainList.at( domainIndex );
509  anDomain.translateDomain(xTranslation, yTranslation, zTranslation);
510 
511  Display3D<TSpace, TKSpace>::updateBoundingBox( anDomain.point1 );
512  Display3D<TSpace, TKSpace>::updateBoundingBox( anDomain.point2 );
513  Display3D<TSpace, TKSpace>::updateBoundingBox( anDomain.point3 );
514  Display3D<TSpace, TKSpace>::updateBoundingBox( anDomain.point4 );
515 
516  std::vector<typename DGtal::Display3D<TSpace, TKSpace>::LineD3D> & vectLines =
517  Viewer3D<TSpace, TKSpace>::myLineSetList.at( anDomain.myLineSetIndex );
518  for(unsigned int i=0; i<vectLines.size(); i++){
519  typename DGtal::Display3D<TSpace, TKSpace>::LineD3D & aLine =
520  vectLines.at( i );
521  aLine.point1[0]=aLine.point1[0]+xTranslation; aLine.point1[1]=aLine.point1[1]+yTranslation; aLine.point1[2]=aLine.point1[2]+zTranslation;
522  aLine.point2[0]=aLine.point2[0]+xTranslation; aLine.point2[1]=aLine.point2[1]+yTranslation; aLine.point2[2]=aLine.point2[2]+zTranslation;
523  }
524 }
525 
526 template <typename TSpace, typename TKSpace>
527 inline std::string
528 DGtal::Viewer3D<TSpace, TKSpace>::TextureImage::className() const
529 {
530  return "TextureImage";
531 }
532 
533 template <typename TSpace, typename TKSpace>
534 inline DGtal::Viewer3D<TSpace, TKSpace> & DGtal::Viewer3D<TSpace, TKSpace>::
535 operator<<( const DGtal::Color & aColor )
536 {
537  myDefaultColor=aColor;
538  return *this;
539 }
540 
541 template <typename TSpace, typename TKSpace>
542 inline DGtal::Viewer3D<TSpace, TKSpace> & DGtal::Viewer3D<TSpace, TKSpace>::
543 operator<<( const typename Viewer3D<TSpace, TKSpace>::StreamKey & key )
544 {
545  switch (key)
546  {
547  case Viewer3D<TSpace, TKSpace>::updateDisplay:
548  Viewer3D<TSpace, TKSpace>::updateList();
549  break;
550 
551  case Viewer3D<TSpace, TKSpace>::addNewList:
552  Viewer3D<TSpace, TKSpace>::createNewCubeList();
553  break;
554 
555  case Viewer3D<TSpace, TKSpace>::shiftSurfelVisu:
556  Viewer3D<TSpace, TKSpace>::myCurrentfShiftVisuPrisms += 0.3;
557  break;
558  }
559  return *this;
560 }
561 
562 template <typename TSpace, typename TKSpace>
563 template <typename TDrawableWithViewer3D>
564 inline DGtal::Viewer3D<TSpace, TKSpace> & DGtal::Viewer3D<TSpace, TKSpace>::
565 operator<<( const TDrawableWithViewer3D & object )
566 {
567  BOOST_CONCEPT_ASSERT((concepts::CDrawableWithViewer3D< TDrawableWithViewer3D, Space, KSpace >));
568 
569  DGtal::Viewer3DFactory<TSpace, TKSpace>::draw( *this, object );
570  return *this;
571 }
572 
573 
574 ///////////////////////////////////////////////////////////////////////////////
575 // Implementation of inline functions and external operators //
576 
577 template <typename TSpace, typename TKSpace>
578 inline std::ostream & DGtal::
579 operator<<( std::ostream & out, const Viewer3D<TSpace, TKSpace> & object )
580 {
581  object.selfDisplay ( out );
582  return out;
583 }
584 
585 // //
586 ///////////////////////////////////////////////////////////////////////////////
587 
588 
589 ///////////////////////////////////////////////////////////////////////////////
590 
591 // heritage of parents templates methods //
592 
593 
594 // end of heritage //
595 ///////////////////////////////////////////////////////////////////////////////
596 
597 ///////////////////////////////////////////////////////////////////////////////
598 
599 // surcharge of parents methods //
600 
601 
602 // end of surcharge //
603 ///////////////////////////////////////////////////////////////////////////////
604 
605 template <typename TSpace, typename TKSpace>
606 inline void DGtal::Viewer3D<TSpace, TKSpace>::drawWithNames()
607 {
608  // JOL: 2014/10/15. This method is called only when the user tries
609  // to select some graphic object through QGLViewer. By default,
610  // selection is left clic + shift key.
611  // JOL: 2014/10/15. This is my addition for interacting with
612  // quads. Seems to work well.
613  if ( myExtension != 0 )
614  myExtension->drawWithNames( *this );
615 
616  glCallList ( myQuadsMapId );
617 
618  glCallList ( myCubesMapId );
619 
620  for ( unsigned int i = 0; i < Viewer3D<TSpace, TKSpace>::myLineSetList.size();
621  i++ )
622  {
623  glCallList( myLineSetListId + i );
624  }
625 
626  for ( unsigned int i = 0;
627  i < Viewer3D<TSpace, TKSpace>::myBallSetList.size(); i++ )
628  {
629  glCallList(myBallSetListId+i);
630  }
631 
632 }
633 
634 template <typename TSpace, typename TKSpace>
635 inline void DGtal::Viewer3D<TSpace, TKSpace>::draw()
636 {
637 
638  glUpdateBackground();
639 
640  if ( myExtension != 0 )
641  myExtension->draw( *this );
642 
643  glPushMatrix();
644  glMultMatrixd ( manipulatedFrame()->matrix() );
645  glPushMatrix();
646  glScalef(myGLScaleFactorX, myGLScaleFactorY, myGLScaleFactorZ);
647 
648  glLightfv(GL_LIGHT0, GL_SPECULAR, myLightSpecularCoeffs);
649  glLightfv(GL_LIGHT0, GL_DIFFUSE, myLightDiffuseCoeffs);
650  glLightfv(GL_LIGHT0, GL_AMBIENT, myLightAmbientCoeffs);
651  if( myLightPositionFixToCamera ){
652  updateLightCoordsFromCamera();
653  }else{
654  updateRelativeCameraFromLightPosition();
655  }
656  glLightfv(GL_LIGHT0, GL_POSITION, myLightPosition);
657 
658  unsigned int i = 0;
659  typename std::vector<
660  typename Viewer3D<TSpace, TKSpace>::ClippingPlaneD3D>::const_iterator it =
661  Viewer3D<TSpace, TKSpace>::myClippingPlaneList.begin();
662 
663  // OpenGL can't draw more than GL_MAX_CLIP_PLANES clipping plane
664  while ( i < GL_MAX_CLIP_PLANES &&
665  it != Viewer3D<TSpace, TKSpace>::myClippingPlaneList.end() )
666  {
667  double eq[ 4 ];
668  eq[ 0 ] = it->a;
669  eq[ 1 ] = it->b;
670  eq[ 2 ] = it->c;
671  eq[ 3 ] = it->d;
672  glEnable( GL_CLIP_PLANE0 + i );
673  glClipPlane( GL_CLIP_PLANE0 + i, eq );
674  i++;
675  it++;
676  }
677  if (i == GL_MAX_CLIP_PLANES)
678  {
679  std::cerr <<"Warning maximal clipping plane added" << std::endl;
680  }
681 
682  Vec centerS = sceneCenter();
683  Vec posCam = camera()->position();
684  double distCam =sqrt ( ( posCam.x-centerS.x ) * ( posCam.x-centerS.x ) +
685  ( posCam.y-centerS.y ) * ( posCam.y-centerS.y ) +
686  ( posCam.z-centerS.z ) * ( posCam.z-centerS.z ) );
687  for(unsigned int j=0; j< myVectTextureImage.size(); j++)
688  {
689  GLTextureImage &textureImg = myVectTextureImage.at(j);
690  glPushName ( textureImg.myTextureName );
691  glEnable(GL_TEXTURE_2D);
692  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
693  glBindTexture(GL_TEXTURE_2D, textureImg.myTextureName);
694  glBegin(GL_QUADS);
695  glColor4ub ( 255.0, 255.0, 255.0, 255.0 );
696  glNormal3d(textureImg.vectNormal[0], textureImg.vectNormal[1], textureImg.vectNormal[2]);
697 
698  glTexCoord2f(0, 0);
699  glVertex3f(textureImg.point1[0], textureImg.point1[1], textureImg.point1[2]);
700  glTexCoord2f(textureImg.myTextureFitX, 0.0);
701  glVertex3f(textureImg.point2[0], textureImg.point2[1], textureImg.point2[2]);
702  glTexCoord2f(textureImg.myTextureFitX, textureImg.myTextureFitY);
703  glVertex3f(textureImg.point3[0], textureImg.point3[1], textureImg.point3[2]);
704  glTexCoord2f(0.0, textureImg.myTextureFitY);
705  glVertex3f(textureImg.point4[0], textureImg.point4[1], textureImg.point4[2]);
706  glEnd();
707  glDisable(GL_TEXTURE_2D);
708 
709  }
710 
711  for ( unsigned int j = 0;
712  j < Viewer3D<TSpace, TKSpace>::myLineSetList.size(); j++ )
713  {
714  if ( Viewer3D<TSpace, TKSpace>::myLineSetList.at( j ).size() != 0 )
715  {
716  glLineWidth(
717  std::max( myGLLineMinWidth,
718  Viewer3D<TSpace, TKSpace>::myLineSetList.at( j ).at( 0 ).width ) );
719  }
720  glCallList(myLineSetListId+j);
721  }
722 
723  glCallList(myPrismListId);
724 
725  glCallList( myCubesMapId );
726 
727  for ( unsigned int j = 0; j < Viewer3D<TSpace, TKSpace>::myBallSetList.size();
728  j++ )
729  {
730  if ( myUseGLPointsForBalls )
731  {
732  if ( Viewer3D<TSpace, TKSpace>::myBallSetList.at( j ).size() != 0 )
733  {
734  glPointSize( std::max(
735  myGLPointMinWidth,
736  ( Viewer3D<TSpace, TKSpace>::myBallSetList.at( j ).at( 0 ).radius ) ) );
737  }
738  }
739  else
740  glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE );
741 
742  glCallList( myBallSetListId + j );
743  glUpdateLightRenderingMode();
744  }
745 
746  glDisable(GL_CULL_FACE);
747  glCallList(myQuadsMapId);
748  if(myViewWire)
749  {
750  glLineWidth(
751  std::max( myGLLineMinWidth,
752  Viewer3D<TSpace, TKSpace>::myMeshDefaultLineWidth / distCam ) );
753  glCallList(myQuadsMapWiredId);
754  }
755 
756  glDisable(GL_CULL_FACE);
757  glCallList(myTriangleSetListId);
758  if(myViewWire)
759  {
760  glLineWidth(
761  std::max( myGLLineMinWidth,
762  Viewer3D<TSpace, TKSpace>::myMeshDefaultLineWidth / distCam ) );
763  glCallList(myTriangleSetListWiredId);
764  }
765 
766  glDisable(GL_CULL_FACE);
767  glCallList(myPolygonSetListId);
768  if(myViewWire)
769  {
770  glLineWidth(
771  std::max( myGLLineMinWidth,
772  Viewer3D<TSpace, TKSpace>::myMeshDefaultLineWidth / distCam ) );
773  glCallList(myPolygonSetListWiredId);
774  }
775 
776  if(myIsMovingLight){
777  drawLight(GL_LIGHT0);
778  }
779 
780  glPopMatrix();
781  glPopMatrix();
782 }
783 
784 template <typename TSpace, typename TKSpace>
785 void DGtal::Viewer3D<TSpace, TKSpace>::selfDisplay( std::ostream & out ) const
786 {
787  out << "[Viewer3D]";
788 }
789 
790 template <typename TSpace, typename TKSpace>
791 bool DGtal::Viewer3D<TSpace, TKSpace>::isValid() const
792 {
793  return true;
794 }
795 
796 template <typename TSpace, typename TKSpace>
797 void DGtal::Viewer3D<TSpace, TKSpace>::init()
798 {
799  if ( myExtension != 0 )
800  myExtension->init( *this );
801  myAutoSaveState = false;
802  myIsMovingLight = false;
803  myLigthRotationStep = 0.01;
804  myRefMouseXPos = 0;
805  myRefMouseYPos = 0;
806 
807  myLightPositionRefCamera[0] = myLightPositionRefCameraDefault[0];
808  myLightPositionRefCamera[1] = myLightPositionRefCameraDefault[1];
809  myLightPositionRefCamera[2] = myLightPositionRefCameraDefault[2];
810  updateLightCoordsFromCamera();
811 
812  glClearColor (0.0, 0.0, 0.0, 0.0);
813  glShadeModel (GL_SMOOTH);
814 
815  glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, myMaterialShininessCoeff);
816  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, myMaterialSpecularCoeffs);
817 
818 
819  glLightfv(GL_LIGHT0, GL_SPECULAR, myLightSpecularCoeffs);
820  glLightfv(GL_LIGHT0, GL_DIFFUSE, myLightDiffuseCoeffs);
821  glLightfv(GL_LIGHT0, GL_AMBIENT, myLightAmbientCoeffs);
822 
823  glLightfv(GL_LIGHT0, GL_POSITION, myLightPosition);
824 
825  glEnable(GL_LIGHTING);
826  glEnable(GL_LIGHT0);
827  glEnable(GL_DEPTH_TEST);
828 
829  Viewer3D<TSpace, TKSpace>::myMeshDefaultLineWidth = 10.0;
830  myNbListe=0;
831  myViewWire=false;
832  setBackgroundColor ( QColor ( 217, 228, 255, 255 ) );
833  setForegroundColor ( QColor ( 217, 22, 25, 255 ) );
834 
835  Viewer3D<TSpace, TKSpace>::createNewCubeList();
836  std::vector<typename Viewer3D<TSpace, TKSpace>::LineD3D> listeLine;
837  Viewer3D<TSpace, TKSpace>::myLineSetList.push_back( listeLine );
838  std::vector<typename Viewer3D<TSpace, TKSpace>::BallD3D> listeBall;
839  Viewer3D<TSpace, TKSpace>::myBallSetList.push_back( listeBall );
840  Viewer3D<TSpace, TKSpace>::myCurrentFillColor = Color( 220, 220, 220 );
841  Viewer3D<TSpace, TKSpace>::myCurrentLineColor = Color( 22, 22, 222, 50 );
842  myDefaultBackgroundColor = Color ( backgroundColor().red(), backgroundColor().green(),
843  backgroundColor().blue() );
844  myIsBackgroundDefault=true;
845  Viewer3D<TSpace, TKSpace>::myBoundingPtLow[ 0 ] =
846  -10.0; // numeric_limits<double>::max( );
847  Viewer3D<TSpace, TKSpace>::myBoundingPtLow[ 1 ] =
848  -10.0; // numeric_limits<double>::max( );
849  Viewer3D<TSpace, TKSpace>::myBoundingPtLow[ 2 ] =
850  -10.0; // numeric_limits<double>::max( );
851 
852  Viewer3D<TSpace, TKSpace>::myBoundingPtUp[ 0 ] =
853  -10.0; // numeric_limits<double>::min( );
854  Viewer3D<TSpace, TKSpace>::myBoundingPtUp[ 1 ] =
855  -10.0; // numeric_limits<double>::min( );
856  Viewer3D<TSpace, TKSpace>::myBoundingPtUp[ 2 ] =
857  -10.0; // numeric_limits<double>::min( );
858  Viewer3D<TSpace, TKSpace>::createNewCubeList();
859  typename std::vector<typename Viewer3D<TSpace, TKSpace>::CubeD3D> aKSCubeList;
860 
861  Viewer3D<TSpace, TKSpace>::myCurrentfShiftVisuPrisms = 0.0;
862  Viewer3D<TSpace, TKSpace>::myDefaultColor = Color( 255, 255, 255 );
863  camera()->showEntireScene();
864  setKeyDescription ( Qt::Key_E, "Export the current display into OFF file (just Cube, surfel and SurfelPrism for now)." );
865  setKeyDescription ( Qt::Key_W, "Switch display with and without wired view of triangle and quad faces." );
866  setKeyDescription ( Qt::Key_T, "Sort elements for display improvements." );
867  setKeyDescription ( Qt::Key_L, "Load last visualisation settings (from a .qglviewer.xml file generated by using SHIFT+L)");
868  setKeyDescription ( Qt::ShiftModifier+Qt::Key_L, "Save visualisation settings." );
869  setKeyDescription ( Qt::Key_B, "Switch background color with White/Black colors." );
870  setKeyDescription ( Qt::Key_C, "Show camera informations." );
871  setKeyDescription ( Qt::Key_R, "Reset default scale for 3 axes to 1.0f." );
872  setKeyDescription ( Qt::Key_D, "Enable/Disable the two side face rendering." );
873  setKeyDescription ( Qt::Key_O, "Switch the ball display mode (quad ball display (default) or OpenGL point)." );
874  setKeyDescription ( Qt::Key_M, "Switch the rendering mode bewteen Default, Metallic and Plastic mode." );
875  setKeyDescription ( Qt::Key_P, "Switch the light source position mode between the camera mode (default: the light source position is fixed according to the camera position) and scene mode (the light source position is fixed according the scene coordinate system)." );
876  setKeyDescription( Qt::Key_Z,
877  "Move away the light source according to the scence "
878  "center (move closer with SHIFT+Z)" );
879  setKeyDescription( Qt::ShiftModifier + Qt::Key_Z,
880  "Move closer the light source according to the scence "
881  "center (move awya with key Z)" );
882 
883 #if !defined (QGLVIEWER_VERSION) || QGLVIEWER_VERSION < 0x020500
884  setMouseBindingDescription((Qt::ControlModifier|Qt::ShiftModifier) + Qt::LeftButton, "move light source position defined in the main coordinate system (an x-axis (resp. y-axis) mouse move changes the azimuth (resp. inclination) angle of the light source). Note that light source is always looking at the center point (0,0,0).");
885 #else
886  setMouseBindingDescription(Qt::KeyboardModifiers( Qt::ControlModifier|Qt::ShiftModifier ), Qt::LeftButton, "move light source position defined in the main coordinate system (an x-axis (resp. y-axis) mouse move changes the azimuth (resp. inclination) angle of the light source). Note that light source is always looking at the center point (0,0,0).");
887 #endif
888 
889 
890  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
891 
892 #if !defined (QGLVIEWER_VERSION) || QGLVIEWER_VERSION < 0x020500
893  setMouseBindingDescription ( Qt::ShiftModifier+Qt::RightButton, "Delete the mouse selected list." );
894 #else
895  setMouseBindingDescription ( Qt::ShiftModifier, Qt::RightButton, "Delete the mouse selected list." );
896 #endif
897 
898  setManipulatedFrame ( new ManipulatedFrame() );
899 }
900 
901 template <typename TSpace, typename TKSpace>
902 void DGtal::Viewer3D<TSpace, TKSpace>::sortSurfelFromCamera()
903 {
904  CompFarthestVoxelFromCamera comp;
905  comp.posCam= camera()->position();
906 
907  for ( auto & mapElem : Viewer3D<TSpace, TKSpace>::myCubesMap )
908 
909  {
910  DGtal::trace.info() << "sort quad size" << mapElem.second.size()
911  << std::endl;
912  sort( mapElem.second.begin(), mapElem.second.end(), comp );
913  }
914  CompFarthestSurfelFromCamera compSurf;
915  DGtal::trace.info() << "sort surfel size"
916  << Viewer3D<TSpace, TKSpace>::myPrismList.size()
917  << std::endl;
918  sort( Viewer3D<TSpace, TKSpace>::myPrismList.begin(),
919  Viewer3D<TSpace, TKSpace>::myPrismList.end(), compSurf );
920 }
921 
922 template <typename TSpace, typename TKSpace>
923 void DGtal::Viewer3D<TSpace, TKSpace>::sortTriangleFromCamera()
924 {
925  CompFarthestTriangleFromCamera comp;
926  comp.posCam= camera()->position();
927  for ( auto & listElem : Viewer3D<TSpace, TKSpace>::myTriangleSetList )
928  {
929  sort( listElem.begin(), listElem.end(), comp );
930  }
931 }
932 
933 template <typename TSpace, typename TKSpace>
934 void DGtal::Viewer3D<TSpace, TKSpace>::sortQuadFromCamera()
935 {
936  CompFarthestSurfelFromCamera comp;
937  comp.posCam= camera()->position();
938 
939  for ( auto & listElem : Viewer3D<TSpace, TKSpace>::myQuadsMap )
940  {
941  DGtal::trace.info() << "sort quad size" << listElem.second.size()
942  << std::endl;
943  sort( listElem.second.begin(), listElem.second.end(), comp );
944  }
945 }
946 
947 template <typename TSpace, typename TKSpace>
948 void DGtal::Viewer3D<TSpace, TKSpace>::sortPolygonFromCamera()
949 {
950  CompFarthestPolygonFromCamera comp;
951  comp.posCam= camera()->position();
952 
953  for ( auto & listElem : Viewer3D<TSpace, TKSpace>::myPolygonSetList )
954  {
955  DGtal::trace.info() << "sort polygon size" << listElem.size() << std::endl;
956  sort( listElem.begin(), listElem.end(), comp );
957  }
958 
959 }
960 
961 template <typename TSpace, typename TKSpace>
962 void DGtal::Viewer3D<TSpace, TKSpace>::postSelection( const QPoint & point )
963 {
964  bool handled = false;
965  if ( myExtension != 0 )
966  handled = myExtension->postSelection( *this, point );
967  if ( handled )
968  return;
969 
970  camera()->convertClickToLine ( point, myOrig, myDir );
971  bool found;
972  this->myPosSelector= point;
973  mySelectedPoint = camera()->pointUnderPixel ( point, found );
974  if ( found )
975  {
976  DGtal::trace.info() << "Element of liste= " << selectedName() << "selected" << std::endl;
977  // JOL: 2014/10/15
978  mySelectedElementId = selectedName();
979  void* aData = 0;
980  SelectCallbackFct fct = getSelectCallback3D( selectedName(), aData );
981  if ( fct ) fct( this, selectedName(), aData );
982  // I leave the remaining code.
983  updateList(false);
984  }else if (mySelectedElementId != -1)
985  {
986  mySelectedElementId = -1;
987  updateList(false);
988  }
989 }
990 
991 template <typename TSpace, typename TKSpace>
992 void DGtal::Viewer3D<TSpace, TKSpace>::updateList(
993 bool needToUpdateBoundingBox )
994 {
995 
996  // glDeleteLists
997  glDeleteLists(myCubesMapId, 1);
998  glDeleteLists(myLineSetListId, myNbLineSetList);
999  glDeleteLists(myBallSetListId, myNbBallSetList);
1000  glDeleteLists(myTriangleSetListId, 1);
1001  glDeleteLists(myTriangleSetListWiredId, 1);
1002  glDeleteLists(myPrismListId, 1);
1003  glDeleteLists(myPolygonSetListId, 1);
1004  glDeleteLists(myPolygonSetListWiredId, 1);
1005  glDeleteLists(myQuadsMapId, 1);
1006  glDeleteLists(myQuadsMapWiredId, 1);
1007 
1008  // Storing ID for each list
1009  myCubesMapId = glGenLists(1);
1010  myLineSetListId =
1011  glGenLists( static_cast<GLsizei>(Viewer3D<TSpace, TKSpace>::myLineSetList.size() ));
1012  myNbLineSetList = static_cast<unsigned int>(Viewer3D<TSpace, TKSpace>::myLineSetList.size());
1013  myBallSetListId =
1014  glGenLists( static_cast<GLsizei>(Viewer3D<TSpace, TKSpace>::myBallSetList.size() ) );
1015  myNbBallSetList = static_cast<unsigned int>(Viewer3D<TSpace, TKSpace>::myBallSetList.size());
1016  myTriangleSetListId = glGenLists(1);
1017  myTriangleSetListWiredId = glGenLists(1);
1018  myCubeSetListWiredId = glGenLists(1);
1019  myPolygonSetListId = glGenLists(1);
1020  myPolygonSetListWiredId = glGenLists(1);
1021  myQuadsMapId = glGenLists(1);
1022  myQuadsMapWiredId = glGenLists(1);
1023  myPrismListId = glGenLists(1);
1024 
1025 
1026  myNbListe=0;
1027 
1028  glEnable ( GL_BLEND );
1029  glEnable ( GL_MULTISAMPLE_ARB );
1030  glEnable ( GL_SAMPLE_ALPHA_TO_COVERAGE_ARB );
1031  glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1032 
1033  glCreateListCubesMaps( Viewer3D<TSpace, TKSpace>::myCubesMap, myCubesMapId );
1034 
1035  glCreateListQuadD3D( Viewer3D<TSpace, TKSpace>::myPrismList, myPrismListId );
1036  myNbListe++;
1037 
1038  for ( unsigned int j = 0; j < Viewer3D<TSpace, TKSpace>::myLineSetList.size();
1039  j++ )
1040  {
1041  glCreateListLines( Viewer3D<TSpace, TKSpace>::myLineSetList.at( j ),
1042  myLineSetListId + j );
1043  myNbListe++;
1044  }
1045 
1046  for ( unsigned int j = 0;
1047  j < Viewer3D<TSpace, TKSpace>::myBallSetList.size(); j++ )
1048  {
1049  glCreateListBalls( Viewer3D<TSpace, TKSpace>::myBallSetList.at( j ),
1050  myBallSetListId + j );
1051  myNbListe++;
1052  }
1053 
1054 
1055  // First list: quad faces.
1056  glCreateListQuadMaps( Viewer3D<TSpace, TKSpace>::myQuadsMap, myQuadsMapId );
1057  myNbListe++;
1058 
1059  // Second list: Wired version of quad face.
1060  glCreateListQuadMapsWired( Viewer3D<TSpace, TKSpace>::myQuadsMap,
1061  myQuadsMapWiredId );
1062  myNbListe++;
1063 
1064  // Third list: Triangle faces.
1065  glCreateListTriangles( Viewer3D<TSpace, TKSpace>::myTriangleSetList,
1066  myTriangleSetListId );
1067  myNbListe++;
1068 
1069  // Fourth list: Wired version of triangle face.
1070  glCreateListTrianglesWired( Viewer3D<TSpace, TKSpace>::myTriangleSetList,
1071  myTriangleSetListWiredId );
1072  myNbListe++;
1073 
1074  // Fifth list: Polygonal faces.
1075  glCreateListPolygons( Viewer3D<TSpace, TKSpace>::myPolygonSetList,
1076  myPolygonSetListId );
1077  myNbListe++;
1078 
1079  // Sixth list: Wired version of polygonal face.
1080  glCreateListPolygonsWired( Viewer3D<TSpace, TKSpace>::myPolygonSetList,
1081  myPolygonSetListWiredId );
1082  myNbListe++;
1083 
1084  // Seventh list: Textured images.
1085  glUpdateTextureImages( myGSImageList );
1086 
1087  if ( needToUpdateBoundingBox &&
1088  Viewer3D<TSpace, TKSpace>::myBoundingPtChangedTag )
1089  {
1090  setSceneBoundingBox(
1091  qglviewer::Vec( Viewer3D<TSpace, TKSpace>::myBoundingPtLow[ 0 ],
1092  Viewer3D<TSpace, TKSpace>::myBoundingPtLow[ 1 ],
1093  Viewer3D<TSpace, TKSpace>::myBoundingPtLow[ 2 ] ),
1094  qglviewer::Vec( Viewer3D<TSpace, TKSpace>::myBoundingPtUp[ 0 ],
1095  Viewer3D<TSpace, TKSpace>::myBoundingPtUp[ 1 ],
1096  Viewer3D<TSpace, TKSpace>::myBoundingPtUp[ 2 ] ) );
1097  showEntireScene();
1098  Viewer3D<TSpace, TKSpace>::myBoundingPtChangedTag = false;
1099  }
1100  update();
1101  glPopMatrix();
1102 }
1103 
1104 template <typename TSpace, typename TKSpace>
1105 void DGtal::Viewer3D<TSpace, TKSpace>::glDrawGLBall(
1106 const typename Viewer3D<TSpace, TKSpace>::BallD3D & aBall )
1107 {
1108  double thetaResolution = aBall.resolution;
1109  double thetaStep= (2.0*M_PI)/thetaResolution;
1110  double phiResolution = aBall.resolution;
1111  double phiStep= M_PI/phiResolution;
1112 
1113  double radius = aBall.radius;
1114  double xCenter = aBall.center[0];
1115  double yCenter = aBall.center[1];
1116  double zCenter = aBall.center[2];
1117  glBegin(GL_QUAD_STRIP);
1118  for(unsigned int j =0; j < phiResolution; j++)
1119  {
1120  double phi0 = M_PI/2.0-j*phiStep;
1121  double phi1 = M_PI/2.0-(j+1)*phiStep;
1122  for(unsigned int i =0; i <= thetaResolution; i++)
1123  {
1124  double theta0 = i * thetaStep;
1125  glColor4ub ( aBall.color.red(), aBall.color.green(), aBall.color.blue(), aBall.color.alpha() );
1126  glNormal3f(cos(phi0)*cos(theta0), cos(phi0)*sin(theta0), sin(phi0));
1127  glVertex3f(xCenter+cos(phi0)*cos(theta0)*radius,yCenter+ cos(phi0)*sin(theta0)*radius, zCenter+ sin(phi0)*radius);
1128  glNormal3f(cos(phi1)*cos(theta0), cos(phi1)*sin(theta0), sin(phi1));
1129  glVertex3f(xCenter+cos(phi1)*cos(theta0)*radius,yCenter+ cos(phi1)*sin(theta0)*radius, zCenter+ sin(phi1)*radius);
1130  }
1131  }
1132  glEnd();
1133 
1134 }
1135 
1136 template <typename TSpace, typename TKSpace>
1137 void DGtal::Viewer3D<TSpace, TKSpace>::mousePressEvent( QMouseEvent * e )
1138 {
1139  bool handled = false;
1140  // Checks if an extension is present.
1141  if ( myExtension != 0 )
1142  {
1143  handled = myExtension->mousePressEvent( *this, e );
1144  if ( handled )
1145  return;
1146  }
1147 
1148  if(e->modifiers() == (Qt::ControlModifier|Qt::ShiftModifier))
1149  {
1150  myIsMovingLight=true;
1151  myRefMouseXPos = e->x();
1152  myRefMouseYPos = e->y();
1153  if( myLightPositionFixToCamera )
1154  {
1155  updateLightCoordsFromCamera();
1156  }
1157  myLightR = sqrt( myLightPosition[0]* myLightPosition[0]+
1158  myLightPosition[1]* myLightPosition[1]+
1159  myLightPosition[2]* myLightPosition[2]);
1160  myLightTheta = asin( myLightPosition[2]/myLightR);
1161  myLightPhi = atan2( myLightPosition[1], myLightPosition[0]);
1162  }
1163  else
1164  {
1165  QGLViewer::mousePressEvent(e);
1166  }
1167 }
1168 
1169 template <typename TSpace, typename TKSpace>
1170 void DGtal::Viewer3D<TSpace, TKSpace>::mouseReleaseEvent( QMouseEvent * e )
1171 {
1172  bool handled = false;
1173  // Checks if an extension is present.
1174  if ( myExtension != 0 )
1175  {
1176  handled = myExtension->mouseReleaseEvent( *this, e );
1177  if ( handled )
1178  return;
1179  }
1180 
1181  if(e->modifiers() == (Qt::ControlModifier|Qt::ShiftModifier) || myIsMovingLight){
1182  myIsMovingLight=false;
1183  update();
1184  }else{
1185  QGLViewer::mouseReleaseEvent(e);
1186  }
1187 }
1188 
1189 template <typename TSpace, typename TKSpace>
1190 void DGtal::Viewer3D<TSpace, TKSpace>::mouseMoveEvent( QMouseEvent * e )
1191 {
1192  bool handled = false;
1193  // Checks if an extension is present.
1194  if ( myExtension != 0 )
1195  {
1196  handled = myExtension->mouseMoveEvent( *this, e );
1197  if ( handled )
1198  return;
1199  }
1200 
1201  if(e->modifiers() == (Qt::ControlModifier|Qt::ShiftModifier)){
1202  int varX = e->x() - myRefMouseXPos;
1203  int varY = e->y() - myRefMouseYPos;
1204  myLightPhi -= varY * myLigthRotationStep;
1205  myLightTheta -= varX * myLigthRotationStep / 2.0;
1206  myLightPosition[0] = myLightR*cos(myLightTheta)*cos(myLightPhi);
1207  myLightPosition[1] = myLightR*cos(myLightTheta)*sin(myLightPhi);
1208  myLightPosition[2] = myLightR*sin(myLightTheta);
1209  if(myLightPositionFixToCamera){
1210  updateRelativeCameraFromLightPosition();
1211  }
1212  glLightfv(GL_LIGHT0, GL_POSITION, myLightPosition);
1213  myRefMouseXPos = e->x();
1214  myRefMouseYPos = e->y();
1215  update();
1216  }else{
1217  QGLViewer::mouseMoveEvent(e);
1218  }
1219 }
1220 
1221 template <typename TSpace, typename TKSpace>
1222 void DGtal::Viewer3D<TSpace, TKSpace>::keyPressEvent( QKeyEvent * e )
1223 {
1224  bool handled = false;
1225  // Checks if an extension is present.
1226  if ( myExtension != 0 )
1227  {
1228  handled = myExtension->keyPressEvent( *this, e );
1229  if ( handled )
1230  return;
1231  }
1232 
1233  if( e->key() == Qt::Key_D)
1234  {
1235  myIsDoubleFaceRendering = !myIsDoubleFaceRendering;
1236  glUpdateLightRenderingMode();
1237  update();
1238 
1239  }
1240  if( e->key() == Qt::Key_E)
1241  {
1242  trace.info() << "Exporting mesh..." ;
1243  operator>><TSpace, TKSpace>( *this, "exportedMesh.off" );
1244  trace.info() << "[done]"<< std::endl ;
1245  }
1246  if( e->key() == Qt::Key_M)
1247  {
1248  switch (myRenderingMode)
1249  {
1250  case RenderingMode::RenderingDefault :
1251  myRenderingMode = RenderingMode::RenderingMetallic;
1252  break;
1253  case RenderingMode::RenderingMetallic :
1254  myRenderingMode = RenderingMode::RenderingPlastic;
1255  break;
1256  case RenderingMode::RenderingPlastic :
1257  myRenderingMode = RenderingMode::RenderingLambertian;
1258  break;
1259  case RenderingMode::RenderingLambertian :
1260  myRenderingMode = RenderingMode::RenderingDefault;
1261  break;
1262  }
1263  updateRenderingCoefficients(myRenderingMode);
1264  }
1265 
1266 
1267 
1268  if ( ( e->key() ==Qt::Key_W ) )
1269  {
1270  myViewWire=!myViewWire;
1271  updateList(false);
1272  update();
1273  }
1274  if ( e->key() == Qt::Key_Z )
1275  {
1276  if ( myLightPositionFixToCamera )
1277  {
1278  updateLightCoordsFromCamera();
1279  }
1280  myLightR = sqrt( myLightPosition[ 0 ] * myLightPosition[ 0 ] +
1281  myLightPosition[ 1 ] * myLightPosition[ 1 ] +
1282  myLightPosition[ 2 ] * myLightPosition[ 2 ] );
1283  myLightTheta = asin( myLightPosition[ 2 ] / myLightR );
1284  myLightPhi = atan2( myLightPosition[ 1 ], myLightPosition[ 0 ] );
1285 
1286  std::stringstream ss;
1287  if ( e->modifiers() == Qt::ShiftModifier )
1288  {
1289  myLightR += 5.0;
1290  ss << "Move away light source at distance: " << myLightR;
1291  }
1292  else
1293  {
1294  myLightR -= 5.0;
1295  ss << "Move closer light source at distance: " << myLightR;
1296  }
1297  displayMessage( QString( ss.str().c_str() ), 3000 );
1298  myLightPosition[ 0 ] = myLightR * cos( myLightTheta ) * cos( myLightPhi );
1299  myLightPosition[ 1 ] = myLightR * cos( myLightTheta ) * sin( myLightPhi );
1300  myLightPosition[ 2 ] = myLightR * sin( myLightTheta );
1301  if ( myLightPositionFixToCamera )
1302  {
1303  updateRelativeCameraFromLightPosition();
1304  }
1305  myIsMovingLight = true;
1306  glLightfv( GL_LIGHT0, GL_POSITION, myLightPosition );
1307  update();
1308  }
1309 
1310  if ( ( e->key() == Qt::Key_P ) )
1311  {
1312  myLightPositionFixToCamera =! myLightPositionFixToCamera;
1313  updateLightCoordsFromCamera();
1314  if(myLightPositionFixToCamera)
1315  {
1316  displayMessage(QString("Light source position fixed to camera."), 3000);
1317  updateRelativeCameraFromLightPosition();
1318  }
1319  else
1320  {
1321  displayMessage(QString("Light source position fixed to main scene."), 3000);
1322  //updateLightCoordsFromCamera();
1323  }
1324  update();
1325  }
1326 
1327  if ( ( e->key() ==Qt::Key_O ) )
1328  {
1329  myUseGLPointsForBalls = !myUseGLPointsForBalls;
1330  updateList(false);
1331  update();
1332  }
1333 
1334  if ( ( e->key() ==Qt::Key_R ) )
1335  {
1336  myGLScaleFactorX=1.0f;
1337  myGLScaleFactorY=1.0f;
1338  myGLScaleFactorZ=1.0f;
1339  update();
1340  }
1341 
1342  if ( ( e->key() ==Qt::Key_T ) )
1343  {
1344  handled=true;
1345  DGtal::trace.info() << "sorting surfel according camera position....";
1346  sortSurfelFromCamera();
1347  sortTriangleFromCamera();
1348  sortQuadFromCamera();
1349  sortPolygonFromCamera();
1350  DGtal::trace.info() << " [done]"<< std::endl;
1351  updateList(false);
1352  update();
1353  }
1354  if ( ( e->key() ==Qt::Key_B ) )
1355  {
1356  handled=true;
1357  myIsBackgroundDefault=!myIsBackgroundDefault;
1358  glUpdateBackground();
1359  update();
1360  }
1361 
1362  if ( ( e->key() ==Qt::Key_L ) )
1363  {
1364  if(e->modifiers()==Qt::ShiftModifier){
1365  saveStateToFile();
1366  }else{
1367  restoreStateFromFile();
1368  update();
1369  }
1370  }
1371  if ( ( e->key() ==Qt::Key_C ) )
1372  {
1373  handled=true;
1374  GLint Viewport[4];
1375  GLdouble Projection[16], Modelview[16];
1376 
1377  glGetIntegerv ( GL_VIEWPORT , Viewport );
1378  glGetDoublev ( GL_MODELVIEW_MATRIX , Modelview );
1379  glGetDoublev ( GL_PROJECTION_MATRIX, Projection );
1380 
1381  for ( unsigned short m=0; m<4; ++m )
1382  {
1383  for ( unsigned short l=0; l<4; ++l )
1384  {
1385  double sum = 0.0;
1386  for ( unsigned short k=0; k<4; ++k )
1387  sum += Projection[l+4*k]*Modelview[k+4*m];
1388  }
1389  }
1390 
1391  DGtal::trace.info() << "Viewport: ";
1392  for ( unsigned short l=0; l<4; ++l )
1393  DGtal::trace.info() << Viewport[l] << ", ";
1394  DGtal::trace.info() << std::endl;
1395 
1396  Vec cp = camera()->position();
1397  Vec cd = camera()->viewDirection();
1398  Vec cup = camera()->upVector();
1399 
1400  DGtal::trace.info() << "camera.position: " ;
1401  for ( unsigned short l=0; l<3; ++l )
1402  DGtal::trace.info() << cp[l] << ", ";
1403  DGtal::trace.info() << std::endl;
1404 
1405  DGtal::trace.info() << "camera.direction: ";
1406  for ( unsigned short l=0; l<3; ++l )
1407  DGtal::trace.info() << cd[l] << ", ";
1408  DGtal::trace.info() << std::endl;
1409 
1410  DGtal::trace.info() << "camera.upVector: ";
1411  for ( unsigned short l=0; l<3; ++l )
1412  DGtal::trace.info() << cup[l] << ", ";
1413  DGtal::trace.info() << std::endl;
1414 
1415  DGtal::trace.info() << "zNear: " << camera()->zNear() << " - zFar: " << camera()->zFar() << std::endl;
1416  }
1417 
1418  if ( !handled )
1419  QGLViewer::keyPressEvent ( e );
1420 }
1421 
1422 template <typename TSpace, typename TKSpace>
1423 QString DGtal::Viewer3D<TSpace, TKSpace>::helpString() const
1424 {
1425  QString text;
1426  if ( myExtension != 0 )
1427  text += myExtension->helpString( *this );
1428 
1429  text += "<h2> Viewer3D</h2>";
1430  text += "Use the mouse to move the camera around the object. ";
1431  text += "You can respectively revolve around, zoom and translate with the three mouse buttons. ";
1432  text += "Left and middle buttons pressed together rotate around the camera view direction axis<br><br>";
1433  text += "Pressing <b>Alt</b> and one of the function keys (<b>F1</b>..<b>F12</b>) defines a camera keyFrame. ";
1434  text += "Simply press the function key again to restore it-> Several keyFrames define a ";
1435  text += "camera path. Paths are saved when you quit the application and restored at next start.<br><br>";
1436  text += "Press <b>F</b> to display the frame rate, <b>A</b> for the world axis, ";
1437  text += "<b>Alt+Return</b> for full screen mode and <b>Control+S</b> to save a snapshot. ";
1438  text += "See the <b>Keyboard</b> tab in this window for a complete shortcut list.<br><br>";
1439  text += "Double clicks automates single click actions: A left button double click aligns the closer axis with the camera (if close enough). ";
1440  text += "A middle button double click fits the zoom of the camera and the right button re-centers the scene.<br><br>";
1441  text += "A left button double click while holding right button pressed defines the camera <i>Revolve Around Ball</i>. ";
1442  text += "See the <b>Mouse</b> tab and the documentation web pages for details.<br><br>";
1443  text += "Press <b>Escape</b> to exit the viewer.";
1444  return text;
1445 }
1446 
1447 template <typename TSpace, typename TKSpace>
1448 void DGtal::Viewer3D<TSpace, TKSpace>::glCreateListCubesMaps(
1449 const typename DGtal::Display3D<TSpace, TKSpace>::CubesMap & aCubeMap,
1450 unsigned int idList )
1451 {
1452  glNewList ( idList , GL_COMPILE );
1453 
1454  for (auto &mapElem: aCubeMap)
1455  {
1456  glPushName ( mapElem.first );
1457  glEnable ( GL_LIGHTING );
1458  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
1459  glBegin ( GL_QUADS );
1460  bool useColorSelection = false;
1461  if(mySelectedElementId == mapElem.first)
1462  useColorSelection = true;
1463 
1464  for (auto &cube: mapElem.second)
1465  {
1466  if(useColorSelection)
1467  {
1468  unsigned char m = (cube.color.red()+ cube.color.green()+ cube.color.blue())/3;
1469  if(m>128)
1470  {
1471  glColor4ub ( std::max((int)(cube.color.red())-mySelectionColorShift, 0),
1472  std::max((int)(cube.color.green())-mySelectionColorShift, 0),
1473  std::max((int)(cube.color.blue())-mySelectionColorShift, 0),
1474  cube.color.alpha());
1475  }
1476  else{
1477  glColor4ub ( std::min(cube.color.red()+mySelectionColorShift, 255),
1478  std::min(cube.color.green()+mySelectionColorShift, 255),
1479  std::min(cube.color.blue()+mySelectionColorShift, 255),
1480  cube.color.alpha());
1481  }
1482  }
1483  else
1484  {
1485  glColor4ub ( cube.color.red(), cube.color.green(), cube.color.blue(),cube.color.alpha());
1486  }
1487  double _width= cube.width;
1488  //z+
1489  glNormal3f ( 0.0, 0.0, 1.0 );
1490  glVertex3f ( cube.center[0]-_width, cube.center[1]+_width, cube.center[2]+_width );
1491  glVertex3f ( cube.center[0]-_width, cube.center[1]-_width, cube.center[2]+_width );
1492  glVertex3f ( cube.center[0]+_width, cube.center[1]-_width, cube.center[2]+_width );
1493  glVertex3f ( cube.center[0]+_width, cube.center[1]+_width, cube.center[2]+_width );
1494  //z-
1495  glNormal3f ( 0.0, 0.0, -1.0 );
1496  glVertex3f ( cube.center[0]-_width, cube.center[1]+_width, cube.center[2]-_width );
1497  glVertex3f ( cube.center[0]+_width, cube.center[1]+_width, cube.center[2]-_width );
1498  glVertex3f ( cube.center[0]+_width, cube.center[1]-_width, cube.center[2]-_width );
1499  glVertex3f ( cube.center[0]-_width, cube.center[1]-_width, cube.center[2]-_width );
1500  //x+
1501  glNormal3f ( 1.0, 0.0, 0.0 );
1502  glVertex3f ( cube.center[0]+_width, cube.center[1]-_width, cube.center[2]+_width );
1503  glVertex3f ( cube.center[0]+_width, cube.center[1]-_width, cube.center[2]-_width );
1504  glVertex3f ( cube.center[0]+_width, cube.center[1]+_width, cube.center[2]-_width );
1505  glVertex3f ( cube.center[0]+_width, cube.center[1]+_width, cube.center[2]+_width );
1506  //x-
1507  glNormal3f ( -1.0, 0.0, 0.0 );
1508  glVertex3f ( cube.center[0]-_width, cube.center[1]-_width, cube.center[2]+_width );
1509  glVertex3f ( cube.center[0]-_width, cube.center[1]+_width, cube.center[2]+_width );
1510  glVertex3f ( cube.center[0]-_width, cube.center[1]+_width, cube.center[2]-_width );
1511  glVertex3f ( cube.center[0]-_width, cube.center[1]-_width, cube.center[2]-_width );
1512  //y+
1513  glNormal3f ( 0.0, 1.0, 0.0 );
1514  glVertex3f ( cube.center[0]-_width, cube.center[1]+_width, cube.center[2]+_width );
1515  glVertex3f ( cube.center[0]+_width, cube.center[1]+_width, cube.center[2]+_width );
1516  glVertex3f ( cube.center[0]+_width, cube.center[1]+_width, cube.center[2]-_width );
1517  glVertex3f ( cube.center[0]-_width, cube.center[1]+_width, cube.center[2]-_width );
1518  //y-
1519  glNormal3f ( 0.0, -1.0, 0.0 );
1520  glVertex3f ( cube.center[0]-_width, cube.center[1]-_width, cube.center[2]+_width );
1521  glVertex3f ( cube.center[0]-_width, cube.center[1]-_width, cube.center[2]-_width );
1522  glVertex3f ( cube.center[0]+_width, cube.center[1]-_width, cube.center[2]-_width );
1523  glVertex3f ( cube.center[0]+_width, cube.center[1]-_width, cube.center[2]+_width );
1524  }
1525  glEnd();
1526  glPopName();
1527  }
1528  glEndList();
1529  glUpdateLightRenderingMode();
1530 
1531 }
1532 
1533 template <typename TSpace, typename TKSpace>
1534 void DGtal::Viewer3D<TSpace, TKSpace>::glCreateListQuadD3D(
1535 const VectorQuad & aVectQuad, unsigned int idList )
1536 {
1537  glNewList ( idList, GL_COMPILE );
1538  glPushName ( myNbListe );
1539  glEnable ( GL_DEPTH_TEST );
1540  glEnable ( GL_BLEND );
1541  glEnable ( GL_MULTISAMPLE_ARB );
1542  glEnable ( GL_SAMPLE_ALPHA_TO_COVERAGE_ARB );
1543  glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1544 
1545  glBegin ( GL_QUADS );
1546  for ( auto const &q: aVectQuad )
1547  {
1548  glColor4ub ( q.color.red(), q.color.green(),
1549  q.color.blue(), q.color.alpha() );
1550  glNormal3f ( q.nx, q.ny, q.nz );
1551  glVertex3f ( q.point1[0], q.point1[1] , q.point1[2] );
1552  glVertex3f ( q.point2[0], q.point2[1] , q.point2[2] );
1553  glVertex3f ( q.point3[0], q.point3[1] , q.point3[2] );
1554  glVertex3f ( q.point4[0], q.point4[1] , q.point4[2] );
1555  }
1556  glEnd();
1557  glEndList();
1558 }
1559 
1560 template <typename TSpace, typename TKSpace>
1561 void DGtal::Viewer3D<TSpace, TKSpace>::glCreateListLines(
1562 const VectorLine & aVectLine, unsigned int idList )
1563 {
1564  glNewList ( idList, GL_COMPILE );
1565  glDisable ( GL_LIGHTING );
1566  glPushName ( myNbListe );
1567  glBegin ( GL_LINES );
1568  for (auto const &l: aVectLine )
1569  {
1570  glColor4ub ( l.color.red(), l.color.green(),
1571  l.color.blue(), l.color.alpha() );
1572  glVertex3f ( l.point1[0], l.point1[1], l.point1[2] );
1573  glVertex3f ( l.point2[0], l.point2[1], l.point2[2] );
1574  }
1575  glEnd();
1576  glEnable ( GL_LIGHTING );
1577  glEndList();
1578 }
1579 
1580 template <typename TSpace, typename TKSpace>
1581 void DGtal::Viewer3D<TSpace, TKSpace>::glCreateListBalls(
1582 const VectorBall & aVectBall, unsigned int idList )
1583 {
1584  if(myUseGLPointsForBalls)
1585  {
1586  glNewList ( idList, GL_COMPILE );
1587  glDepthMask ( GL_TRUE );
1588  glDisable ( GL_TEXTURE_2D );
1589  glDisable ( GL_POINT_SMOOTH );
1590  glDisable ( GL_LIGHTING );
1591  glPushName ( myNbListe );
1592  glBegin ( GL_POINTS );
1593  for ( auto const &ball: aVectBall )
1594  {
1595  glColor4ub ( ball.color.red(), ball.color.green(),
1596  ball.color.blue(), ball.color.alpha() );
1597  glVertex3f ( ball.center[0], ball.center[1], ball.center[2] );
1598  }
1599  glEnd();
1600  glEnable ( GL_LIGHTING );
1601  glEndList();
1602  }
1603  else
1604  {
1605  glNewList ( idList, GL_COMPILE );
1606  glPushName ( myNbListe );
1607  glDepthMask ( GL_TRUE );
1608  glDisable ( GL_TEXTURE_2D );
1609  glDisable ( GL_POINT_SMOOTH );
1610  for ( auto const & b: aVectBall)
1611  {
1612  glDrawGLBall ( b );
1613  }
1614  glEnd();
1615  glEndList();
1616  }
1617 }
1618 
1619 template <typename TSpace, typename TKSpace>
1620 void DGtal::Viewer3D<TSpace, TKSpace>::glCreateListQuadMaps(
1621 const typename DGtal::Display3D<TSpace, TKSpace>::QuadsMap & aQuadMap,
1622 unsigned int idList )
1623 {
1624  glNewList ( idList, GL_COMPILE );
1625  for (auto & mapElem: aQuadMap)
1626  {
1627  glPushName ( mapElem.first );
1628  glEnable ( GL_LIGHTING );
1629  glBegin ( GL_QUADS );
1630  bool useColorSelection = false;
1631  if(mySelectedElementId == mapElem.first)
1632  useColorSelection = true;
1633 
1634  for (auto &q: mapElem.second)
1635  {
1636  if(useColorSelection)
1637  {
1638  unsigned char m = (q.color.red()+ q.color.green()+ q.color.blue())/3;
1639  if(m>128)
1640  {
1641  glColor4ub ( std::max((int)(q.color.red())-mySelectionColorShift, 0),
1642  std::max((int)(q.color.green())-mySelectionColorShift, 0),
1643  std::max((int)(q.color.blue())-mySelectionColorShift, 0),
1644  q.color.alpha());
1645  }
1646  else{
1647  glColor4ub ( std::min(q.color.red()+mySelectionColorShift, 255),
1648  std::min(q.color.green()+mySelectionColorShift, 255),
1649  std::min(q.color.blue()+mySelectionColorShift, 255),
1650  q.color.alpha());
1651  }
1652  }
1653  else
1654  {
1655  glColor4ub ( q.color.red(), q.color.green(), q.color.blue(), q.color.alpha());
1656 
1657  }
1658 
1659  glNormal3f ( q.nx, q.ny ,q.nz );
1660  glVertex3f ( q.point1[0], q.point1[1], q.point1[2] );
1661  glVertex3f ( q.point2[0], q.point2[1], q.point2[2] );
1662  glVertex3f ( q.point3[0], q.point3[1], q.point3[2] );
1663  glVertex3f ( q.point4[0], q.point4[1], q.point4[2] );
1664  }
1665  glEnd();
1666  glPopName();
1667  }
1668  glEndList();
1669 }
1670 
1671 template <typename TSpace, typename TKSpace>
1672 void DGtal::Viewer3D<TSpace, TKSpace>::glCreateListQuadMapsWired(
1673 const typename DGtal::Display3D<TSpace, TKSpace>::QuadsMap & aQuadMap,
1674 unsigned int idList )
1675 {
1676  glNewList ( idList, GL_COMPILE );
1677  glPushName ( myNbListe );
1678  glDisable ( GL_LIGHTING );
1679  glBegin ( GL_LINES );
1680 
1681  for (auto const &mapElem: aQuadMap)
1682  {
1683  for(auto const &q: mapElem.second)
1684  {
1685  glColor4ub ( 150.0,150.0,150.0,255.0 );
1686  glColor4ub( Viewer3D<TSpace, TKSpace>::myCurrentLineColor.red(),
1687  Viewer3D<TSpace, TKSpace>::myCurrentLineColor.green(),
1688  Viewer3D<TSpace, TKSpace>::myCurrentLineColor.blue(),
1689  Viewer3D<TSpace, TKSpace>::myCurrentLineColor.alpha() );
1690  glVertex3f ( q.point1[0], q.point1[1], q.point1[2] );
1691  glVertex3f ( q.point2[0], q.point2[1], q.point2[2] );
1692  glVertex3f ( q.point2[0], q.point2[1], q.point2[2] );
1693  glColor4ub( Viewer3D<TSpace, TKSpace>::myCurrentLineColor.red(),
1694  Viewer3D<TSpace, TKSpace>::myCurrentLineColor.green(),
1695  Viewer3D<TSpace, TKSpace>::myCurrentLineColor.blue(),
1696  Viewer3D<TSpace, TKSpace>::myCurrentLineColor.alpha() );
1697  glVertex3f ( q.point3[0], q.point3[1], q.point3[2] );
1698  glVertex3f ( q.point3[0], q.point3[1], q.point3[2] );
1699  glVertex3f ( q.point4[0], q.point4[1], q.point4[2] );
1700  glColor4ub( Viewer3D<TSpace, TKSpace>::myCurrentLineColor.red(),
1701  Viewer3D<TSpace, TKSpace>::myCurrentLineColor.green(),
1702  Viewer3D<TSpace, TKSpace>::myCurrentLineColor.blue(),
1703  Viewer3D<TSpace, TKSpace>::myCurrentLineColor.alpha() );
1704  glVertex3f ( q.point4[0], q.point4[1], q.point4[2] );
1705  glVertex3f ( q.point1[0], q.point1[1], q.point1[2] );
1706  }
1707  }
1708  glEnd();
1709  glEndList();
1710 
1711 }
1712 
1713 template <typename TSpace, typename TKSpace>
1714 void DGtal::Viewer3D<TSpace, TKSpace>::glCreateListTriangles(
1715 const std::vector<VectorTriangle> & aVectTriangle, unsigned int idList )
1716 {
1717  glNewList ( idList, GL_COMPILE );
1718  glPushName ( myNbListe );
1719  glEnable ( GL_LIGHTING );
1720  glBegin ( GL_TRIANGLES );
1721  for(auto const &tList: aVectTriangle)
1722  {
1723  for (auto const &t: tList)
1724  {
1725  glColor4ub (t.color.red(),t.color.green(),t.color.blue(),t.color.alpha() );
1726  glNormal3f (t.nx,t.ny ,t.nz );
1727  glVertex3f (t.point1[0],t.point1[1],t.point1[2] );
1728  glVertex3f (t.point2[0],t.point2[1],t.point2[2] );
1729  glVertex3f (t.point3[0],t.point3[1],t.point3[2] );
1730  }
1731  }
1732  glEnd();
1733  glEndList();
1734 }
1735 
1736 template <typename TSpace, typename TKSpace>
1737 void DGtal::Viewer3D<TSpace, TKSpace>::glCreateListTrianglesWired(
1738 const std::vector<VectorTriangle> & aVectTriangle, unsigned int idList )
1739 {
1740  glNewList ( idList, GL_COMPILE );
1741  glPushName ( myNbListe );
1742  glDisable ( GL_LIGHTING );
1743  glBegin ( GL_LINES );
1744  for (auto const &tList: aVectTriangle)
1745  {
1746  for (auto const &t: tList)
1747  {
1748  glColor4ub( Viewer3D<TSpace, TKSpace>::myCurrentLineColor.red(),
1749  Viewer3D<TSpace, TKSpace>::myCurrentLineColor.green(),
1750  Viewer3D<TSpace, TKSpace>::myCurrentLineColor.blue(),
1751  Viewer3D<TSpace, TKSpace>::myCurrentLineColor.alpha() );
1752  glVertex3f (t.point1[0],t.point1[1],t.point1[2] );
1753  glVertex3f (t.point2[0],t.point2[1],t.point2[2] );
1754  glVertex3f (t.point2[0],t.point2[1],t.point2[2] );
1755  glVertex3f (t.point3[0],t.point3[1],t.point3[2] );
1756  glVertex3f (t.point3[0],t.point3[1],t.point3[2] );
1757  glVertex3f (t.point1[0],t.point1[1],t.point1[2] );
1758  }
1759  }
1760  glEnd();
1761  glEndList();
1762 
1763 }
1764 
1765 template <typename TSpace, typename TKSpace>
1766 void DGtal::Viewer3D<TSpace, TKSpace>::glCreateListPolygons(
1767 const std::vector<VectorPolygon> & aVectPolygon, unsigned int idList )
1768 {
1769  glNewList ( idList, GL_COMPILE );
1770  glPushName ( myNbListe );
1771  glEnable ( GL_LIGHTING );
1772 
1773  for(auto const &pList: aVectPolygon)
1774  {
1775  for (auto const &p: pList)
1776  {
1777  glBegin ( GL_POLYGON );
1778  glColor4ub ( p.color.red(), p.color.green(), p.color.blue(), p.color.alpha() );
1779  glNormal3f ( p.nx, p.ny ,p.nz );
1780  for(unsigned int j=0;j < (p.vertices).size();j++)
1781  {
1782  glVertex3f ( (p.vertices).at(j)[0], (p.vertices).at(j)[1], (p.vertices).at ( j )[2] );
1783  }
1784  glEnd();
1785  }
1786  }
1787  glEndList();
1788 }
1789 
1790 template <typename TSpace, typename TKSpace>
1791 void DGtal::Viewer3D<TSpace, TKSpace>::glCreateListPolygonsWired(
1792 const std::vector<VectorPolygon> & aVectPolygon, unsigned int idList )
1793 {
1794  glNewList ( idList, GL_COMPILE );
1795  glPushName ( myNbListe );
1796  glDisable ( GL_LIGHTING );
1797  glBegin ( GL_LINES );
1798  for(auto const &pList: aVectPolygon)
1799  {
1800  for (auto const &p: pList)
1801  {
1802  glColor4ub( Viewer3D<TSpace, TKSpace>::myCurrentLineColor.red(),
1803  Viewer3D<TSpace, TKSpace>::myCurrentLineColor.green(),
1804  Viewer3D<TSpace, TKSpace>::myCurrentLineColor.blue(),
1805  Viewer3D<TSpace, TKSpace>::myCurrentLineColor.alpha() );
1806  for(unsigned int j=0;j < (p.vertices).size();j++)
1807  {
1808  glVertex3f ( (p.vertices).at(j)[0], (p.vertices).at(j)[1], (p.vertices).at ( j )[2] );
1809  glVertex3f ( (p.vertices).at((j+1)%(p.vertices).size())[0],
1810  (p.vertices).at((j+1)%(p.vertices).size())[1],
1811  (p.vertices).at ( (j+1)%(p.vertices).size() )[2] );
1812  }
1813  }
1814  }
1815  glEnd();
1816  glEndList();
1817 }
1818 
1819 template <typename TSpace, typename TKSpace>
1820 void DGtal::Viewer3D<TSpace, TKSpace>::glUpdateTextureImages(
1821 const VectorTextureImage & aVectImage )
1822 {
1823 
1824  for(unsigned int j=0; j<myVectTextureImage.size(); j++){
1825  glDeleteTextures(1,&(myVectTextureImage[j].myTextureName));
1826  }
1827  myVectTextureImage.clear();
1828  for(unsigned int j=0; j<aVectImage.size(); j++)
1829  {
1830  typename Viewer3D<TSpace, TKSpace>::TextureImage aGSImage =
1831  aVectImage.at( j );
1832  GLTextureImage textureImg(aGSImage);
1833 
1834  glGenTextures(1, &textureImg.myTextureName);
1835  glBindTexture(GL_TEXTURE_2D, textureImg.myTextureName);
1836 
1837  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1838  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1839  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1840  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1841  if ( textureImg.myMode == Viewer3D<TSpace, TKSpace>::GrayScaleMode )
1842  {
1843  glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, textureImg.myBufferWidth,
1844  textureImg.myBufferHeight, 0, GL_LUMINANCE,
1845  GL_UNSIGNED_BYTE, textureImg.myTextureImageBufferGS );
1846  }
1847  else if ( textureImg.myMode == Viewer3D<TSpace, TKSpace>::RGBMode )
1848  {
1849  glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, textureImg.myBufferWidth,
1850  textureImg.myBufferHeight, 0, GL_RGB, GL_UNSIGNED_BYTE,
1851  textureImg.myTextureImageBufferRGB );
1852  }
1853  myVectTextureImage.push_back(textureImg);
1854  }
1855 }
1856 
1857 template <typename TSpace, typename TKSpace>
1858 void DGtal::Viewer3D<TSpace, TKSpace>::glUpdateLightRenderingMode() const
1859 {
1860  if(myIsDoubleFaceRendering)
1861  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
1862  else
1863  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
1864 }
1865 
1866 
1867 template <typename TSpace, typename TKSpace>
1868 void DGtal::Viewer3D<TSpace, TKSpace>::glUpdateBackground()
1869 {
1870 
1871  if ( !myIsBackgroundDefault )
1872  {
1873  setBackgroundColor ( QColor ( 255, 255,255, 255 ) );
1874  }
1875  else
1876  {
1877  setBackgroundColor ( QColor ( myDefaultBackgroundColor.red(),
1878  myDefaultBackgroundColor.green(),
1879  myDefaultBackgroundColor.blue(),
1880  myDefaultBackgroundColor.alpha()));
1881  }
1882 }
1883 
1884 
1885 template <typename TSpace, typename TKSpace>
1886 QDomElement
1887 DGtal::Viewer3D<TSpace, TKSpace>::domElement( const QString & name,
1888  QDomDocument & document ) const
1889 {
1890  // Creates a custom node for a light position
1891  QDomElement deRendering = document.createElement("Rendering");
1892  deRendering.setAttribute("mode", myRenderingMode);
1893  QDomElement de = document.createElement("Light");
1894  de.setAttribute("pos_light_x", myLightPosition[0]);
1895  de.setAttribute("pos_light_y", myLightPosition[1]);
1896  de.setAttribute("pos_light_z", myLightPosition[2]);
1897  // Get default state domElement and append custom node
1898  QDomElement res = QGLViewer::domElement(name, document);
1899  res.appendChild(de);
1900  res.appendChild(deRendering);
1901  return res;
1902 }
1903 
1904 template <typename TSpace, typename TKSpace>
1905 void DGtal::Viewer3D<TSpace, TKSpace>::initFromDOMElement(
1906 const QDomElement & element )
1907 {
1908  // Restore standard state
1909  QGLViewer::initFromDOMElement(element);
1910  QDomElement child=element.firstChild().toElement();
1911  while (!child.isNull())
1912  {
1913  if (child.tagName() == "Rendering")
1914  {
1915  myRenderingMode = (RenderingMode)(child.attribute("mode").toInt());
1916  }
1917  if (child.tagName() == "Light")
1918  {
1919  if (child.hasAttribute("pos_light_x"))
1920  {
1921  myLightPosition[0] = child.attribute("pos_light_x").toDouble();
1922  }
1923 
1924  if (child.hasAttribute("pos_light_y"))
1925  {
1926  myLightPosition[1] = child.attribute("pos_light_y").toDouble();
1927  }
1928  if (child.hasAttribute("pos_light_z"))
1929  {
1930  myLightPosition[2] = child.attribute("pos_light_z").toDouble();
1931  }
1932  }
1933  child = child.nextSibling().toElement();
1934  }
1935  if(myLightPositionFixToCamera){
1936  updateRelativeCameraFromLightPosition();
1937  }
1938  updateRenderingCoefficients(myRenderingMode, false);
1939  update();
1940 }
1941 
1942 template <typename TSpace, typename TKSpace>
1943 void DGtal::Viewer3D<TSpace, TKSpace>::closeEvent( QCloseEvent * e )
1944 {
1945  if (myAutoSaveState)
1946  {
1947  saveStateToFile();
1948  }
1949  QGLViewer::closeEvent(e);
1950 }
1951 
1952 template <typename TSpace, typename TKSpace>
1953 void DGtal::Viewer3D<TSpace, TKSpace>::setGLDoubleRenderingMode(
1954 bool doubleSidedRendering )
1955 {
1956  myIsDoubleFaceRendering = doubleSidedRendering;
1957  glUpdateLightRenderingMode();
1958 }
1959 
1960 template <typename TSpace, typename TKSpace>
1961 void DGtal::Viewer3D<TSpace, TKSpace>::setGLMaterialShininessCoefficient(
1962 const GLfloat matShininessCoeff )
1963 {
1964  myMaterialShininessCoeff = matShininessCoeff;
1965  update();
1966 }
1967 
1968 template <typename TSpace, typename TKSpace>
1969 void DGtal::Viewer3D<TSpace, TKSpace>::setGLLightAmbientCoefficients(
1970 const GLfloat lightAmbientCoeffs[ 4 ] )
1971 {
1972  myLightAmbientCoeffs[0] = lightAmbientCoeffs[0];
1973  myLightAmbientCoeffs[1] = lightAmbientCoeffs[1];
1974  myLightAmbientCoeffs[2] = lightAmbientCoeffs[2];
1975  myLightAmbientCoeffs[3] = lightAmbientCoeffs[3];
1976  update();
1977 }
1978 
1979 template <typename TSpace, typename TKSpace>
1980 void DGtal::Viewer3D<TSpace, TKSpace>::setGLLightDiffuseCoefficients(
1981 const GLfloat lightDiffuseCoeffs[ 4 ] )
1982 {
1983  myLightDiffuseCoeffs[0] = lightDiffuseCoeffs[0];
1984  myLightDiffuseCoeffs[1] = lightDiffuseCoeffs[1];
1985  myLightDiffuseCoeffs[2] = lightDiffuseCoeffs[2];
1986  myLightDiffuseCoeffs[3] = lightDiffuseCoeffs[3];
1987  update();
1988 }
1989 
1990 template <typename TSpace, typename TKSpace>
1991 void DGtal::Viewer3D<TSpace, TKSpace>::setUseGLPointForBalls(
1992 const bool useOpenGLPt )
1993 {
1994  myUseGLPointsForBalls = useOpenGLPt;
1995 }
1996 
1997 template <typename TSpace, typename TKSpace>
1998 void DGtal::Viewer3D<TSpace, TKSpace>::updateRenderingCoefficients(
1999 const RenderingMode aRenderMode, bool displayState )
2000 {
2001  std::stringstream ss;
2002  ss << "Rendering mode ";
2003 
2004  GLfloat newCoefDiff, newCoefSpec = 1.0f;
2005  switch (aRenderMode)
2006  {
2007  case RenderingMode::RenderingDefault :
2008  newCoefDiff = myDefaultRenderDiff;
2009  newCoefSpec = myDefaultRenderSpec;
2010  ss << "Default (diffuse with few specular)";
2011  break;
2012  case RenderingMode::RenderingMetallic :
2013  newCoefDiff = myMetallicRenderDiff;
2014  newCoefSpec = myMetallicRenderSpec;
2015  ss << "Metallic (diffuse with specular)";
2016  break;
2017  case RenderingMode::RenderingPlastic :
2018  newCoefDiff = myPlasticRenderDiff;
2019  newCoefSpec = myPlasticRenderSpec;
2020  ss << "Plastic (few diffuse with large specular)";
2021  break;
2022  case RenderingMode::RenderingLambertian :
2023  newCoefDiff = myLambertRenderDiff;
2024  newCoefSpec = myLambertRenderSpec;
2025  ss << "Lambertian (only diffuse)";
2026  break;
2027  }
2028  for (unsigned int i = 0; i<3; i++)
2029  myLightDiffuseCoeffs[i] = newCoefDiff;
2030  myLightDiffuseCoeffs[3] = 1.0;
2031  for (unsigned int i = 0; i<3; i++)
2032  myLightSpecularCoeffs[i] = newCoefSpec;
2033  myLightSpecularCoeffs[3] = 1.0;
2034  if (displayState)
2035  {
2036  displayMessage(QString(ss.str().c_str()), 3000);
2037  }
2038  update();
2039 }
2040 
2041 template <typename TSpace, typename TKSpace>
2042 void DGtal::Viewer3D<TSpace, TKSpace>::setGLLightSpecularCoefficients(
2043 const GLfloat lightSpecularCoeffs[ 4 ] )
2044 {
2045  myLightSpecularCoeffs[0] = lightSpecularCoeffs[0];
2046  myLightSpecularCoeffs[1] = lightSpecularCoeffs[1];
2047  myLightSpecularCoeffs[2] = lightSpecularCoeffs[2];
2048  myLightSpecularCoeffs[3] = lightSpecularCoeffs[3];
2049  update();
2050 }
2051 
2052 template <typename TSpace, typename TKSpace>
2053 inline void DGtal::Viewer3D<TSpace, TKSpace>::show()
2054 {
2055  QGLViewer::show();
2056  updateList(false);
2057 }
2058 
2059 template <typename TSpace, typename TKSpace>
2060 inline void DGtal::Viewer3D<TSpace, TKSpace>::paintGL()
2061 {
2062  if ( displaysInStereo() )
2063  {
2064  for ( int view = 1; view >= 0; --view )
2065  {
2066  // Clears screen, set model view matrix with shifted matrix for ith buffer
2067  preDrawStereo( view );
2068  postDraw();
2069  // Used defined method. Default is empty
2070  if ( camera()->frame()->isManipulated() )
2071  fastDraw();
2072  else
2073  draw();
2074  }
2075  }
2076  else
2077  {
2078  // Clears screen, set model view matrix...
2079  preDraw();
2080  postDraw();
2081  // Used defined method. Default calls draw()
2082  if ( camera()->frame()->isManipulated() )
2083  fastDraw();
2084  else
2085  draw();
2086  // Add visual hints: axis, camera, grid...
2087  }
2088  Q_EMIT drawFinished( true );
2089 }
2090 
2091 template <typename TSpace, typename TKSpace>
2092 void DGtal::Viewer3D<TSpace, TKSpace>::updateLightCoordsFromCamera()
2093 {
2094  Vec posLCam;
2095  posLCam[0] = myLightPositionRefCamera[0];
2096  posLCam[1] = myLightPositionRefCamera[1];
2097  posLCam[2] = myLightPositionRefCamera[2];
2098  Vec posL = camera()->worldCoordinatesOf(posLCam);
2099  myLightPosition[0] = static_cast<GLfloat>(posL[0]);
2100  myLightPosition[1] = static_cast<GLfloat>(posL[1]);
2101  myLightPosition[2] = static_cast<GLfloat>(posL[2]);
2102  myLightPosition[3] = 1.0f;
2103 }
2104 
2105 template <typename TSpace, typename TKSpace>
2106 void DGtal::Viewer3D<TSpace, TKSpace>::updateRelativeCameraFromLightPosition()
2107 {
2108  Vec posL;
2109  posL[0] = myLightPosition[0];
2110  posL[1] = myLightPosition[1];
2111  posL[2] = myLightPosition[2];
2112  Vec posLCam = camera()->cameraCoordinatesOf(posL);
2113  myLightPositionRefCamera[0] = static_cast<GLfloat>(posLCam[0]);
2114  myLightPositionRefCamera[1] = static_cast<GLfloat>(posLCam[1]);
2115  myLightPositionRefCamera[2] = static_cast<GLfloat>(posLCam[2]);
2116 }
2117 
2118 
2119