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