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