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