GLC_lib  2.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
glc_viewport.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 
3  This file is part of the GLC-lib library.
4  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
5  http://glc-lib.sourceforge.net
6 
7  GLC-lib is free software; you can redistribute it and/or modify
8  it under the terms of the GNU Lesser General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11 
12  GLC-lib is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with GLC-lib; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21 *****************************************************************************/
22 
24 
25 #include <QtOpenGL>
26 
27 #include "../glu/glc_glu.h"
28 #include "glc_viewport.h"
29 #include "../glc_openglexception.h"
30 #include "../glc_ext.h"
31 #include "../shading/glc_selectionmaterial.h"
32 #include "../glc_state.h"
33 #include "../sceneGraph/glc_3dviewinstance.h"
34 
35 #include <QtDebug>
36 
37 using namespace glc;
39 // Constructor Destructor
41 
43 // Camera definition
44 : m_pViewCam(new GLC_Camera()) // Camera
45 , m_DistanceMax(500.0) // Camera Maximum distance
46 , m_dDistanceMini(0.01) // Camera Minimum distance
47 , m_ViewAngle(35) // Camera angle of view
48 , m_ViewTangent(tan(glc::toRadian(m_ViewAngle)))
49 , m_pImagePlane(NULL) // Background image
50 // OpenGL Window size
51 , m_Width(0) // Horizontal OpenGL viewport size
52 , m_Height(0) // Vertical OpenGL viewport size
53 , m_AspectRatio(1.0)
54 // the default backgroundColor
55 , m_BackgroundColor(Qt::black)
56 , m_SelectionSquareSize(4)
57 , m_ProjectionMatrix()
58 , m_Frustum()
59 , m_ClipPlanesHash()
60 , m_UseClipPlane(false)
61 , m_3DWidgetCollection()
62 , m_UseParallelProjection(false)
63 , m_MinimumStaticPixelSize(10)
64 , m_MinimumStaticRatioSize(0.0)
65 , m_MinimumDynamicRatioSize(0.0)
66 {
68 }
69 
71 {
72  delete m_pViewCam;
73 
74  // delete background image
76 
77  // Delete clip planes
78  QHash<GLenum, GLC_Plane*>::iterator iClip= m_ClipPlanesHash.begin();
79  while (m_ClipPlanesHash.constEnd() != iClip)
80  {
81  delete iClip.value();
82  ++iClip;
83  }
84 }
85 
86 QSize GLC_Viewport::size() const
87 {
88  return QSize(m_Width, m_Height);
89 }
90 
92 // Get Functions
95 {
96  double nX= 0.0;
97  double nY= 0.0;
98  if (m_Width != 0)
99  {
100  nX= static_cast<double>(x) / static_cast<double>(m_Width);
101  }
102 
103  if (m_Height != 0)
104  {
105  nY= static_cast<double>(y) / static_cast<double>(m_Height);
106  }
107 
108  return GLC_Point2d(nX, nY);
109 }
110 
112 {
114 
115  return mapNormalyzeToOpenGLScreen(nPos.x(), nPos.y());
116 }
117 
119 {
120  GLC_Point2d pos(x, y);
121  pos= pos * 2.0;
122  pos.setY(pos.y() * -1.0);
123  pos= pos + GLC_Point2d(-1.0, 1.0);
124  return pos;
125 }
126 
127 GLC_Vector3d GLC_Viewport::mapPosMouse( GLdouble Posx, GLdouble Posy) const
128 {
129  // Change the window origin (Up Left -> centred)
130  Posx= Posx - static_cast<double>(m_Width) / 2.0;
131  Posy= static_cast<double>(m_Height) / 2.0 - Posy;
132 
133  GLC_Vector3d VectMouse(Posx, Posy,0);
134 
135  // Compute the length of camera's field of view
136  const double ChampsVision = m_pViewCam->distEyeTarget() * m_ViewTangent;
137 
138  // the side of camera's square is mapped on Vertical length of window
139  // Ratio OpenGL/Pixel = dimend GL / dimens Pixel
140  const double Ratio= ChampsVision / static_cast<double>(m_Height);
141 
142  VectMouse= VectMouse * Ratio;
143 
144  return VectMouse;
145 }
146 
147 GLC_Vector3d GLC_Viewport::mapNormalyzePosMouse(double Posx, double Posy) const
148 {
149  double screenX= Posx * static_cast<double>(m_Width);
150  double screenY= Posy * static_cast<double>(m_Height);
151  return mapPosMouse(screenX, screenY);
152 }
153 
155 // Public OpenGL Functions
157 
159 {
160  glClearColor(m_BackgroundColor.redF(), m_BackgroundColor.greenF(), m_BackgroundColor.blueF(), 1.0f);
161  glClearDepth(1.0f); // Depth Buffer Setup
162  glShadeModel(GL_SMOOTH); // Enable Smooth Shading
163  glEnable(GL_DEPTH_TEST); // Enables Depth Testing
164  glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
165  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculation
166  glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
167  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
168  glPolygonOffset (1.0f, 1.0f);
169 }
170 
172 {
175 }
176 
178 {
179  GLC_Context::current()->glcMatrixMode(GL_PROJECTION); // select The Projection Matrix
180  GLC_Context::current()->glcLoadIdentity(); // Reset The Projection Matrix
181 
183  {
184  const double height= m_pViewCam->distEyeTarget() * m_ViewTangent;
185  const double with= height * m_AspectRatio;
186  const double left= -with * 0.5;
187  const double right= -left;
188  const double bottom= - height * 0.5;
189  const double top= -bottom;
190  GLC_Context::current()->glcOrtho(left, right, bottom, top, m_dDistanceMini, m_DistanceMax);
191  }
192  else
193  {
194  const double yMax= m_dDistanceMini * tan(m_ViewAngle * glc::PI / 360.0);
195  const double yMin= -yMax;
196  const double xMax= yMax * m_AspectRatio;
197  const double xMin= -xMax;
198  GLC_Context::current()->glcFrustum(xMin, xMax, yMin, yMax, m_dDistanceMini, m_DistanceMax);
199  }
200 
201  // Save the projection matrix
203 
204  GLC_Context::current()->glcMatrixMode(GL_MODELVIEW); // select The Modelview Matrix
205 }
206 
208 {
209  m_AspectRatio= ratio;
211 }
212 
214 {
215  // Update The Aspect Ratio Of The Window
216  m_AspectRatio= static_cast<double>(m_Width)/static_cast<double>(m_Height);
217 }
219 {
220  const int halfSize= m_SelectionSquareSize / 2;
221  // Calculate the 4 points of the selection
222  //p1->p2
223  //
224  //p0 p3
225  QList<int> coordinates;
226  // Point 0
227  coordinates << (x - halfSize) << (y + halfSize);
228  // Point 1
229  coordinates << (x - halfSize) << (y - halfSize);
230  // Point 2
231  coordinates << (x + halfSize) << (y - halfSize);
232  // Point 3
233  coordinates << (x + halfSize) << (y + halfSize);
234 
235  // Unproject the 4 point
236  QList<GLC_Point3d> listOfPoint= unproject(coordinates);
237 
238  Q_ASSERT(4 == listOfPoint.size());
239  // Create the four frustum planes
240  GLC_Point3d eye= m_pViewCam->eye();
241  const GLC_Plane leftPlane(listOfPoint.at(0), listOfPoint.at(1), eye);
242  const GLC_Plane rightPlane(listOfPoint.at(3), eye , listOfPoint.at(2));
243  const GLC_Plane upPlane(listOfPoint.at(2), eye, listOfPoint.at(1));
244  const GLC_Plane bottomPlane(listOfPoint.at(0), eye, listOfPoint.at(3));
245 
247  selectionFrustum.setLeftClippingPlane(leftPlane);
248  selectionFrustum.setRightClippingPlane(rightPlane);
249  selectionFrustum.setTopClippingPlane(upPlane);
250  selectionFrustum.setBottomClippingPlane(bottomPlane);
251 
252  return selectionFrustum;
253 }
254 
255 GLC_Point3d GLC_Viewport::unProject(int x, int y, GLenum buffer) const
256 {
257  // Z Buffer component of the given coordinate is between 0 and 1
258  GLfloat Depth;
259  // read selected point
260  glReadBuffer(buffer);
261  glReadPixels(x, m_Height - y , 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &Depth);
262 
263  // The current viewport opengl definition
264  GLint Viewport[4];
265  glGetIntegerv(GL_VIEWPORT, Viewport);
266 
267  // OpenGL ccordinate of selected point
268  GLdouble pX, pY, pZ;
269  glc::gluUnProject((GLdouble) x, (GLdouble) (m_Height - y) , Depth
270  , m_pViewCam->modelViewMatrix().getData(), m_ProjectionMatrix.getData(), Viewport, &pX, &pY, &pZ);
271 
272  return GLC_Point3d(pX, pY, pZ);
273 }
274 
275 QList<GLC_Point3d> GLC_Viewport::unproject(const QList<int>& list, GLenum buffer)const
276 {
277  const int size= list.size();
278  Q_ASSERT((size % 2) == 0);
279 
280  // The current viewport opengl definition
281  GLint Viewport[4];
282  glGetIntegerv(GL_VIEWPORT, Viewport);
283 
284  // Z Buffer component of the given coordinate is between 0 and 1
285  GLfloat Depth;
286 
287  // Coordinate of readed points
288  GLdouble pX, pY, pZ;
289  QList<GLC_Point3d> unprojectedPoints;
290  for (int i= 0; i < size; i+= 2)
291  {
292  const int x= list.at(i);
293  const int y= m_Height - list.at(i + 1);
294  glReadBuffer(buffer);
295  glReadPixels(x, y , 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &Depth);
296 
297  glc::gluUnProject(static_cast<GLdouble>(x), static_cast<GLdouble>(y) , Depth , m_pViewCam->modelViewMatrix().getData()
298  , m_ProjectionMatrix.getData(), Viewport, &pX, &pY, &pZ);
299  unprojectedPoints.append(GLC_Point3d(pX, pY, pZ));
300  }
301 
302  return unprojectedPoints;
303 }
304 
306 // Private OpenGL Functions
308 
310 {
311 
313  {
314  if (m_pImagePlane != NULL)
315  {
317  }
318  }
319 }
320 
322 {
325 }
327 // Set Functions
329 
330 void GLC_Viewport::setWinGLSize(int width, int height, bool updateOGLViewport)
331 {
332  m_Width= width;
333  m_Height= height;
334 
335  // Prevent A Divide By Zero By
336  if (m_Height == 0)
337  {
338  m_Height= 1;
339  }
340 
343 
344  if (updateOGLViewport)
345  {
346  glViewport(0,0,m_Width,m_Height);
348  }
349 }
350 
351 void GLC_Viewport::setWinGLSize(const QSize &size, bool updateOGLViewport)
352 {
353  setWinGLSize(size.width(), size.height(), updateOGLViewport);
354 }
355 
356 GLC_uint GLC_Viewport::renderAndSelect(int x, int y, GLenum buffer)
357 {
358  const QColor clearColor(Qt::black);
359  glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), 1.0f);
361  // Draw the scene
362  emit updateOpenGL();
364 
365  return selectOnPreviousRender(x, y, buffer);
366 }
367 
368 GLC_uint GLC_Viewport::selectOnPreviousRender(int x, int y, GLenum buffer)
369 {
370  GLsizei width= m_SelectionSquareSize;
371  GLsizei height= width;
372  GLint newX= x - width / 2;
373  GLint newY= (m_Height - y) - height / 2;
374  if (newX < 0) newX= 0;
375  if (newY < 0) newY= 0;
376 
377  return meaningfulIdInsideSquare(newX, newY, width, height, buffer);
378 }
379 GLC_uint GLC_Viewport::selectBody(GLC_3DViewInstance* pInstance, int x, int y, GLenum buffer)
380 {
381  const QColor clearColor(Qt::black);
382  glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), 1.0f);
384  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
386 
387  glExecuteCam();
388 
389  // Draw the scene
390  glDisable(GL_BLEND);
392  glDisable(GL_TEXTURE_2D);
393 
394  pInstance->renderForBodySelection();
396 
397  GLsizei width= 6;
398  GLsizei height= width;
399  GLint newX= x - width / 2;
400  GLint newY= (m_Height - y) - height / 2;
401  if (newX < 0) newX= 0;
402  if (newY < 0) newY= 0;
403 
404  return meaningfulIdInsideSquare(newX, newY, width, height, buffer);
405 }
406 
407 QPair<int, GLC_uint> GLC_Viewport::selectPrimitive(GLC_3DViewInstance* pInstance, int x, int y, GLenum buffer)
408 {
409  QPair<int, GLC_uint> result;
410 
411  const QColor clearColor(Qt::black);
412  glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), 1.0f);
414  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
416 
417  glExecuteCam();
418 
419  // Draw the scene
420  glDisable(GL_BLEND);
422  glDisable(GL_TEXTURE_2D);
423 
424  pInstance->renderForBodySelection();
425 
426 
427  GLsizei width= 6;
428  GLsizei height= width;
429  GLint newX= x - width / 2;
430  GLint newY= (m_Height - y) - height / 2;
431  if (newX < 0) newX= 0;
432  if (newY < 0) newY= 0;
433 
434  GLC_uint bodyId= meaningfulIdInsideSquare(newX, newY, width, height, buffer);
435  if (bodyId == 0)
436  {
437  result.first= -1;
438  result.second= 0;
439  }
440  else
441  {
442  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
443 
444  result.first= pInstance->renderForPrimitiveSelection(bodyId);
445  result.second= meaningfulIdInsideSquare(newX, newY, width, height, buffer);
446  }
448  return result;
449 }
450 
451 QSet<GLC_uint> GLC_Viewport::selectInsideSquare(int x1, int y1, int x2, int y2, GLenum buffer)
452 {
453  if (x1 > x2)
454  {
455  int xTemp= x1;
456  x1= x2;
457  x2= xTemp;
458  }
459  if (y2 > y1)
460  {
461  int yTemp= y1;
462  y1= y2;
463  y2= yTemp;
464  }
465  const QColor clearColor(Qt::black);
466  glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), 1.0f);
468  // Draw the scene
469  updateOpenGL();
471 
472  GLsizei width= x2 - x1;
473  GLsizei height= y1 - y2;
474  GLint newX= x1;
475  GLint newY= (m_Height - y1);
476  if (newX < 0) newX= 0;
477  if (newY < 0) newY= 0;
478 
479  return listOfIdInsideSquare(newX, newY, width, height, buffer);
480 }
481 
482 GLC_uint GLC_Viewport::meaningfulIdInsideSquare(GLint x, GLint y, GLsizei width, GLsizei height, GLenum buffer)
483 {
484  const int squareSize= width * height;
485  const GLsizei arraySize= squareSize * 4; // 4 -> R G B A
486  QVector<GLubyte> colorId(arraySize);
487 
488  // Get the array of pixels
489  glReadBuffer(buffer);
490  glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, colorId.data());
491 
492  // Restore Background color
493  glClearColor(m_BackgroundColor.redF(), m_BackgroundColor.greenF(), m_BackgroundColor.blueF(), 1.0f);
494 
495  QHash<GLC_uint, int> idHash;
496  QList<int> idWeight;
497 
498  // Find the most meaningful color
499  GLC_uint returnId= 0;
500  // There is nothing at the center
501  int maxWeight= 0;
502  int currentIndex= 0;
503  for (int i= 0; i < squareSize; ++i)
504  {
505  GLC_uint id= glc::decodeRgbId(&colorId[i * 4]);
506  if (idHash.contains(id))
507  {
508  const int currentWeight= ++(idWeight[idHash.value(id)]);
509  if (maxWeight < currentWeight)
510  {
511  returnId= id;
512  maxWeight= currentWeight;
513  }
514  }
515  else if (id != 0)
516  {
517  idHash.insert(id, currentIndex++);
518  idWeight.append(1);
519  if (maxWeight < 1)
520  {
521  returnId= id;
522  maxWeight= 1;
523  }
524  }
525  }
526 
527  return returnId;
528 }
529 
530 QSet<GLC_uint> GLC_Viewport::listOfIdInsideSquare(GLint x, GLint y, GLsizei width, GLsizei height, GLenum buffer)
531 {
532  const int squareSize= width * height;
533  const GLsizei arraySize= squareSize * 4; // 4 -> R G B A
534  QVector<GLubyte> colorId(arraySize);
535 
536  // Get the array of pixels
537  glReadBuffer(buffer);
538  glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, colorId.data());
539 
540  // Restore Background color
541  glClearColor(m_BackgroundColor.redF(), m_BackgroundColor.greenF(), m_BackgroundColor.blueF(), 1.0f);
542 
543  QSet<GLC_uint> idSet;
544 
545  // get the color inside square
546  for (int i= 0; i < squareSize; ++i)
547  {
548  GLC_uint id= glc::decodeRgbId(&colorId[i * 4]);
549  idSet << id;
550  }
551 
552  return idSet;
553 }
554 
556 {
557  int size= qMax(m_Width, m_Height);
558  m_MinimumStaticRatioSize= static_cast<double>(m_MinimumStaticPixelSize) / static_cast<double>(size) * 100.0;
560 }
561 
562 void GLC_Viewport::loadBackGroundImage(const QString& ImageFile)
563 {
564  delete m_pImagePlane;
565  m_pImagePlane= new GLC_ImagePlane(ImageFile);
566 }
567 
568 void GLC_Viewport::loadBackGroundImage(const QImage& image)
569 {
570  delete m_pImagePlane;
571  m_pImagePlane= new GLC_ImagePlane(image);
572 }
573 
575 {
576  delete m_pImagePlane;
577  m_pImagePlane= NULL;
578 }
579 
580 void GLC_Viewport::clearBackground(const QColor& color) const
581 {
582  glClearColor(color.redF(), color.greenF(), color.blueF(), 1.0f);
583 }
584 
585 void GLC_Viewport::setToOrtho(bool useOrtho)
586 {
587  if (m_UseParallelProjection != useOrtho)
588  {
591  }
592 
593 }
594 
595 void GLC_Viewport::reframe(const GLC_BoundingBox& box, double coverFactor)
596 {
597  Q_ASSERT(!box.isEmpty());
598 
599  // Center view on the BoundingBox
600  const GLC_Vector3d deltaVector(box.center() - m_pViewCam->target());
601  m_pViewCam->translate(deltaVector);
602 
603  if (coverFactor > 0.0) {
604  double cameraCover= box.boundingSphereRadius() * coverFactor;
605 
606  // Compute Camera distance
607  const double distance = cameraCover / m_ViewTangent;
608 
609  // Update Camera position
610  m_pViewCam->setDistEyeTarget(distance);
611  }
612 }
613 
614 bool GLC_Viewport::setDistMin(double DistMin)
615 {
616  DistMin= fabs(DistMin);
617  if (DistMin < m_DistanceMax)
618  {
619  m_dDistanceMini= DistMin;
620 
621  updateProjectionMat(); // Update OpenGL projection matrix
622 
623  return true;
624  }
625  else
626  {
627  qDebug("GLC_Viewport::SetDistMin : KO");
628  return false;
629  }
630 
631 }
632 
633 bool GLC_Viewport::setDistMax(double DistMax)
634 {
635  DistMax= fabs(DistMax);
636  if (DistMax > m_dDistanceMini)
637  {
638  m_DistanceMax= DistMax;
639 
640  // Update OpenGL projection matrix
642 
643  return true;
644  }
645  else
646  {
647  qDebug("GLC_Viewport::SetDistMax : KO");
648  return false;
649  }
650 }
651 
653 {
654  if(!bBox.isEmpty())
655  {
656  // The scene is not empty
658 
659  // The bounding Box in Camera coordinate
660  GLC_BoundingBox boundingBox(bBox);
661  boundingBox.transform(matComp);
662 
663  // Increase size of the bounding box
664  const double increaseFactor= 1.1;
665  // Convert box distance in sphere distance
666  const double center= fabs(boundingBox.center().z());
667  const double radius= boundingBox.boundingSphereRadius();
668  const double min= center - radius * increaseFactor;
669  const double max= center + radius * increaseFactor;
670 
671  GLC_Point3d camEye(m_pViewCam->eye());
672  camEye= matComp * camEye;
673 
674  if ((min > 0.0) || (m_UseParallelProjection))
675  {
676  // Outside bounding Sphere
677  m_dDistanceMini= min;
678  m_DistanceMax= max;
679  //qDebug() << "distmin" << m_dDistanceMini;
680  //qDebug() << "distmax" << m_DistanceMax;
681  }
682  else
683  {
684  // Inside bounding Sphere
685  m_dDistanceMini= qMin(0.01 * radius, m_pViewCam->distEyeTarget() / 4.0);
686  m_DistanceMax= max;
687  //qDebug() << "inside distmin" << m_dDistanceMini;
688  //qDebug() << "inside distmax" << m_DistanceMax;
689  }
690  }
691  else
692  {
693  // The scene is empty
696  }
697 
698  // Update OpenGL projection matrix
700 }
701 
702 void GLC_Viewport::setBackgroundColor(QColor setColor)
703 {
704  m_BackgroundColor= setColor;
705  glClearColor(m_BackgroundColor.redF(), m_BackgroundColor.greenF(), m_BackgroundColor.blueF(), 1.0f);
706 }
707 
708 void GLC_Viewport::addClipPlane(GLenum planeGlEnum,GLC_Plane* pPlane)
709 {
710  if (m_ClipPlanesHash.contains(planeGlEnum))
711  {
712  delete m_ClipPlanesHash.value(planeGlEnum);
713  m_ClipPlanesHash.remove(planeGlEnum);
714  }
715  m_ClipPlanesHash.insert(planeGlEnum, pPlane);
716 }
717 
718 void GLC_Viewport::removeClipPlane(GLenum planeGlEnum)
719 {
720  if (m_ClipPlanesHash.contains(planeGlEnum))
721  {
722  delete m_ClipPlanesHash.value(planeGlEnum);
723  m_ClipPlanesHash.remove(planeGlEnum);
724  }
725  else
726  {
727  qDebug() << "GLC_Viewport::removeClipPlane Clipp plane " << planeGlEnum << " Not found";
728  }
729 }
730 
732 {
733  // Delete clip planes
734  QHash<GLenum, GLC_Plane*>::iterator iClip= m_ClipPlanesHash.begin();
735  while (m_ClipPlanesHash.constEnd() != iClip)
736  {
737  delete iClip.value();
738  ++iClip;
739  }
740 }
741 
743 {
744  m_UseClipPlane= flag;
745  if (m_UseClipPlane)
746  {
747  QHash<GLenum, GLC_Plane*>::iterator iClip= m_ClipPlanesHash.begin();
748  while (m_ClipPlanesHash.constEnd() != iClip)
749  {
750  GLenum planeKey= iClip.key();
751  GLC_Plane* pPlane= iClip.value();
752 
753  glClipPlane (planeKey, pPlane->data());
754  glEnable (planeKey);
755  ++iClip;
756  }
757  }
758  else
759  {
760  QHash<GLenum, GLC_Plane*>::iterator iClip= m_ClipPlanesHash.begin();
761  while (m_ClipPlanesHash.constEnd() != iClip)
762  {
763  glDisable(iClip.key());
764  ++iClip;
765  }
766  }
767 
768 }

©2005-2013 Laurent Ribon