Developer Documentation
QtBaseViewer.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 
51 
52 
53 //=============================================================================
54 //
55 // CLASS glViewer - IMPLEMENTATION
56 //
57 //=============================================================================
58 
59 
60 //== INCLUDES =================================================================
61 
62 #include <ACG/GL/acg_glew.hh>
63 
64 #include "QtBaseViewer.hh"
65 #include "QtGLViewerLayout.hh"
66 #include "PostProcessing.hh"
67 
68 #include <ACG/QtWidgets/QtWheel.hh>
69 #include <ACG/Scenegraph/CoordsysNode.hh>
71 #include <ACG/GL/GLError.hh>
72 #include <ACG/GL/IRenderer.hh>
73 
74 #include <QGraphicsWidget>
75 #include <QString>
76 #include <QGLFormat>
77 #include <QBoxLayout>
78 #include <QtNetwork/QUdpSocket>
79 #include <QToolBar>
80 #include <QGraphicsSceneDragDropEvent>
81 #include <QPropertyAnimation>
82 
83 #include <QMimeData>
84 
85 #include <QClipboard>
86 #include <QApplication>
87 #include <QSplitter>
88 #include <QColorDialog>
89 
90 #include <QGraphicsView>
91 #include <QGraphicsProxyWidget>
92 
93 #include <QImageWriter>
94 
95 #if QT_VERSION < 0x050000
96 #include <QGLFramebufferObject>
97 #else
98 #include <QOpenGLFramebufferObject>
99 #endif
100 
101 #ifdef max
102 # undef max
103 #endif
104 
105 #ifdef min
106 # undef min
107 #endif
108 
110 #include <OpenFlipper/common/ViewObjectMarker.hh>
111 
113 
114 #include <OpenFlipper/common/RendererInfo.hh>
115 
116 //== NAMESPACES ===============================================================
117 
118 
119 
120 //== IMPLEMENTATION ==========================================================
121 
122 static const char COPY_PASTE_VIEW_START_STRING[] =
123  "ACG::QtWidgets::QGLViewerWidget encoded view";
124 
125 //== IMPLEMENTATION ==========================================================
126 
127 
128 glViewer::glViewer( QGraphicsScene* _scene,
129  QGLWidget* _glWidget,
130  Viewer::ViewerProperties& _properties,
131  QGraphicsWidget* _parent) :
132  QGraphicsWidget(_parent),
133  glareaGrabbed_(false),
134  projectionUpdateLocked_(false),
135  glScene_(_scene),
136  glWidget_(_glWidget),
137  pickCache_(0),
138  updatePickCache_(true),
139  pickCacheSupported_(true),
140  constrainedRotationAxis_(std::numeric_limits<double>::quiet_NaN(), 0, 0),
141  clickEvent_(QEvent::MouseButtonPress, QPoint (), Qt::NoButton, Qt::NoButton, Qt::NoModifier),
142  properties_(_properties),
143  glstate_(0),
144  initialized_(false),
145  flyAnimationPerspective_(0),
146  flyAnimationOrthogonal_(0),
147  flyAngle_(0.0),
148  currentAnimationPos_(0.0),
149  flyMoveBack_(false),
150  postproc_(0)
151 {
152 
153  // widget stuff
154  createWidgets();
155 
156  // bind GL context to GL state class
157  glstate_ = new ACG::GLState();
159 
160  // state
161  isRotating_ = false;
162  lookAround_ = false;
163 
164  sceneGraphRoot_ = 0;
165 
166  normalsMode_ = NORMALIZE_NORMALS;
167  projectionMode_ = PERSPECTIVE_PROJECTION;
168  navigationMode_ = NORMAL_NAVIGATION;
169 
170  trackMouse_ = false;
171 
172  // Note: we start locked (initialization of updateLocked_)
173  // will be unlocked in initializeGL()
174 
175  QSizePolicy sp = sizePolicy();
176  sp.setHorizontalPolicy( QSizePolicy::Expanding );
177  sp.setVerticalPolicy( QSizePolicy::Expanding );
178  sp.setHorizontalStretch( 1 );
179  sp.setVerticalStretch( 1 );
180  setSizePolicy( sp );
181 
182  redrawTime_.start ();
183 
184  // timer for animation
185  timer_ = new QTimer( this );
186  connect( timer_, SIGNAL(timeout()), this, SLOT( slotAnimation()) );
187 
188  fovyModifier_ = 1.0;
189 
190  allowRotation_ = true;
191 
192 
193  connect( &properties_,SIGNAL(updated()), this, SLOT( slotPropertiesUpdated() ) );
194 
195 
196  //check for updated properties once
198 
199  setAcceptDrops(true);
200 
201  setHome();
202 
203  clickTimer_.setSingleShot (true);
204  connect (&clickTimer_, SIGNAL(timeout ()), this, SLOT(slotClickTimeout ()));
205 }
206 
207 
208 //-----------------------------------------------------------------------------
209 
210 
212 {
213  delete glstate_;
214 }
215 
216 
217 //-----------------------------------------------------------------------------
218 
219 
220 //QSizeF
221 //glViewer::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const
222 //{
223 // return QSizeF( 600, 600 );
224 //}
225 
226 //-----------------------------------------------------------------------------
227 
228 
230  glWidget_->makeCurrent();
231 }
232 
234  glWidget_->swapBuffers();
235 }
236 
237 
238 //-----------------------------------------------------------------------------
239 
241  unsigned int _maxPasses,
242  ACG::Vec3d _bbmin,
243  ACG::Vec3d _bbmax,
244  const bool _resetTrackBall)
245 {
246  sceneGraphRoot_ = _root;
247 
248  if (sceneGraphRoot_ )
249  {
250 
251  // set max number of render pass
252  glstate_->set_max_render_passes(_maxPasses);
253 
254  if ( ( _bbmin[0] > _bbmax[0] ) ||
255  ( _bbmin[1] > _bbmax[1] ) ||
256  ( _bbmin[2] > _bbmax[2] ) ) {
257 
258  // Invalid bounding box, try to recover
259  setScenePos( properties_.sceneCenter() , properties_.sceneRadius(), _resetTrackBall );
260 
261  // Update bounding box to match the scene geometry after recovery
262  _bbmin = ACG::Vec3d(-1.0,-1.0,-1.0);
263  _bbmax = ACG::Vec3d( 1.0, 1.0, 1.0);
264  } else {
265 
266  // For very small scenes, we set the scene radius to 0.1
267  // otherwise we take the real radius
268  if ( ( _bbmax - _bbmin ).max() < OpenFlipperSettings().value("Core/Gui/glViewer/minimalSceneSize",0.1).toDouble() ) {
269  setScenePos( ( _bbmin + _bbmax ) * 0.5,
270  OpenFlipperSettings().value("Core/Gui/glViewer/minimalSceneSize",0.1).toDouble(),
271  _resetTrackBall);
272 
273  } else {
274  setScenePos( ( _bbmin + _bbmax ) * 0.5,
275  ( _bbmax - _bbmin ).norm() * 0.5,
276  _resetTrackBall);
277  }
278 
279  }
280 
281  // remember the new bounding box for the state
282  glstate_->set_bounding_box(_bbmin,_bbmax);
283 
284  }
285 
286 
287  updateGL();
288 
289  emit(signalSceneGraphChanged(sceneGraphRoot_));
290 }
291 
292 
293 //-----------------------------------------------------------------------------
294 
295 
296 void glViewer::trackMouse(bool _track)
297 {
298  trackMouse_ = _track;
299 }
300 
301 
302 //-----------------------------------------------------------------------------
303 
305  // Find coordsys node
306  ACG::SceneGraph::BaseNode* node = 0;
307  node = PluginFunctions::getSceneGraphRootNode()->find("Core Coordsys Node");
308 
309  // set the projection mode for the coordinate system node
310  if (node != 0) {
311  ACG::SceneGraph::CoordsysNode* cnode = dynamic_cast<ACG::SceneGraph::CoordsysNode*> (node);
312  if (_mode == ORTHOGRAPHIC_PROJECTION) {
314  } else {
316  }
317  }
318 }
319 
320 
321 //-----------------------------------------------------------------------------
322 
323 
325 {
327  updateGL();
328 }
329 
330 
332 {
334  updateGL();
335 }
336 
337 
339 {
340  if (projectionMode_ == ORTHOGRAPHIC_PROJECTION)
342  else
344 
345  updateGL();
346 }
347 
348 
350 {
351  if ((projectionMode_ = _p) == ORTHOGRAPHIC_PROJECTION)
352  emit projectionModeChanged( true );
353  else
354  emit projectionModeChanged( false );
355 
357 
359 
360  emit viewChanged();
361 }
362 
364 {
365  if (navigationMode_ == NORMAL_NAVIGATION)
367  else
369 }
370 
371 
373 {
374  if ((navigationMode_ = _n) == NORMAL_NAVIGATION)
375  emit navigationModeChanged( true );
376  else
377  emit navigationModeChanged( false );
378 }
379 
380 void glViewer::setFOVY(double _fovy) {
381 
382  if(_fovy <= 0.0 || _fovy >= 180) {
383  std::cerr << "Error: Minimum or maximum fovy angle exceeded!" << std::endl;
384  return;
385  }
386 
387  OpenFlipperSettings().setValue("Core/Projection/FOVY", _fovy);
389 }
390 
392 {
393  if( projectionUpdateLocked_ )
394  return;
395 
396  makeCurrent();
397 
399 
400  const double aspect = _aspect ? _aspect : this->aspect_ratio();
401  // In stereo mode we have to use a perspective matrix
402  if ( projectionMode_ == PERSPECTIVE_PROJECTION)
403  {
404 
405  // Get fovy
406  const double fovy = this->field_of_view_vertical();
407 
408  glstate_->perspective(fovy, (GLdouble) aspect,
409  near_plane(), far_plane());
410  }
411  else
412  {
413 
415  -ortho_width() / aspect, ortho_width() / aspect,
416  near_plane(), far_plane() );
417  }
418 
419 }
420 
421 
422 //-----------------------------------------------------------------------------
423 
424 
425 void glViewer::setScenePos(const ACG::Vec3d& _center, double _radius, const bool _resetTrackBall)
426 {
427  if(_resetTrackBall) {
428  properties_.trackballCenter(_center);
429  }
430 
431  properties_.sceneCenter(_center);
432 
433  properties_.sceneRadius(_radius);
434  properties_.trackballRadius(_radius);
435 
437 
438  double nearPlane = std::max(0.0001f * properties_.sceneRadius(), -(c[2] + properties_.sceneRadius()));
439  double farPlane = std::max(0.0002f * properties_.sceneRadius(), -(c[2] - properties_.sceneRadius()));
440 
441  // Safety check, if near < 0
442  if ( nearPlane <= 0.0 ) {
443  std::cerr << "Error in BaseViewer drawScene, nearplane <= 0.0" << std::endl;
444  nearPlane = 0.000000000000001;
445  }
446 
447  // Safety check. Make sure that they are in the right order
448  if ( nearPlane > farPlane ) {
449  std::cerr << "Error in BaseViewer setScenePos, Nearplane > Farplane" << std::endl;
450  std::swap(nearPlane,farPlane);
451  }
452 
453  properties_.setPlanes(nearPlane,farPlane);
454 
456  updateGL();
457 
458  emit viewChanged();
459 }
460 
461 
462 //----------------------------------------------------------------------------
463 
464 
465 void glViewer::viewingDirection( const ACG::Vec3d& _dir, const ACG::Vec3d& _up )
466 {
467  // calc eye point for this direction
468  ACG::Vec3d eye = properties_.sceneCenter() - _dir * ( 3.0 * properties_.sceneRadius());
469 
472 
473  emit viewChanged();
474 }
475 
476 //-----------------------------------------------------------------------------
477 
478 void glViewer::lookAt(const ACG::Vec3d& _eye, const ACG::Vec3d& _center, const ACG::Vec3d& _up) {
479 
481  glstate_->lookAt(_eye, _center, _up);
482 
483  properties_.sceneCenter( _center );
484  properties_.sceneRadius( (properties_.sceneCenter() - _eye).norm() );
485 
486  emit viewChanged();
487 }
488 
489 //-----------------------------------------------------------------------------
490 
492 {
493  makeCurrent();
494 
495  switch(normalsMode_ = _mode)
496  {
497  case DONT_TOUCH_NORMALS:
498  ACG::GLState::disable(GL_NORMALIZE);
499  break;
500 
501  case NORMALIZE_NORMALS:
502  ACG::GLState::enable(GL_NORMALIZE);
503  break;
504  }
505 
506  updateGL();
507 }
508 
509 
510 //-----------------------------------------------------------------------------
511 
512 
513 void
514 glViewer::copyToImage( QImage& _image,
515  unsigned int _l, unsigned int _t,
516  unsigned int _w, unsigned int _h,
517  GLenum /* _buffer */ )
518 {
519 
520 // makeCurrent();
521 
522  _image = glWidget_->grabFrameBuffer(true).copy (_l, _t, _w, _h).convertToFormat (QImage::Format_RGB32);
523 }
524 
525 
526 //-----------------------------------------------------------------------------
527 
528 
530 {
531  if (!properties_.updateLocked() && isVisible() )
532  {
533  updatePickCache_ = true;
534  update();
535 
536  emit viewUpdated();
537  }
538 }
539 
540 
541 
542 //-----------------------------------------------------------------------------
543 
544 
545 void glViewer::drawScene(double _aspect)
546 {
547 
548  // Inside the glWidget rendering, the system should not send extra updates
549  properties_.blockSignals(true);
550 
551  QTime timer;
552  timer.start();
553 
554  // *****************************************************************
555  // Adjust clipping planes
556  // *****************************************************************
557  // Far plane
559 
560  double nearPlane = std::max(0.0001f * properties_.sceneRadius(), -(c[2] + properties_.sceneRadius()));
561  double farPlane = std::max(0.0002f * properties_.sceneRadius(), -(c[2] - properties_.sceneRadius()));
562 
563  // Safety check, if near < 0
564  if ( nearPlane <= 0.0 ) {
565  std::cerr << "Error in BaseViewer drawScene, nearplane < 0" << std::endl;
566  nearPlane = 0.000000000000001;
567  }
568 
569  // Safety check. Make sure that they are in the right order
570  if ( nearPlane > farPlane ) {
571  std::cerr << "Error in BaseViewer drawScene, Nearplane > Farplane" << std::endl;
572  std::swap(nearPlane,farPlane);
573  }
574 
575  properties_.setPlanes(nearPlane,farPlane);
576 
577  updateProjectionMatrix(_aspect);
578 
579  // store time since last repaint in gl state and restart timer
580  glstate_->set_msSinceLastRedraw (redrawTime_.restart ());
581 
582  makeCurrent();
583 
584  // draw mono or stereo
585  // If stereo mode is selected, we have to provide multiple ways of rendering.
586 
587  // 1. Default internal pipeline : Directly to output buffer (no stereo support!)
588  // 2. Non default : Non-stereo Directly to output buffer (no stereo support!)
589  //
590  //
591 
592 // if (OpenFlipper::Options::stereoMode () == OpenFlipper::Options::OpenGL && OpenFlipper::Options::glStereo ())
593 // {
594 // // Stereo : Hardware support (OpenGL stereo : left and right buffer with offset eyes)
595 //
596 // return;
597 // }
598 // else if (OpenFlipper::Options::stereoMode () == OpenFlipper::Options::AnaglyphCustom && customAnaglyphSupported_)
599 // {
600 // //Stereo : No Hardware support (Left and right frame buffer with offset eyes)
601 // } else {
602 //
603 // }
604 
605  // save hardware backbuffer
606  GLuint backbufferFbo = 0;
607  GLuint backbufferTarget = 0;
608  glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&backbufferFbo);
609  glGetIntegerv(GL_DRAW_BUFFER, (GLint*)&backbufferTarget);
610 
611 
612 
613  // Render plugins do not have to worry about using scissor test for clearing their viewports later on.
614  glClearColor(properties_.backgroundColor()[0], properties_.backgroundColor()[1],
616  GLint curViewport[4];
617  glGetIntegerv(GL_VIEWPORT, curViewport);
618  glScissor(curViewport[0], curViewport[1], curViewport[2], curViewport[3]);
619  glEnable(GL_SCISSOR_TEST);
620  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
621  glDisable(GL_SCISSOR_TEST);
622 
623 
624 
625  // setup scene target fbo
626  if (!postproc_)
627  postproc_ = new PostProcessing();
628 
629  const int numPostProcessors = postProcessorManager().numActive(properties_.viewerId());
630 
631  bool stereoOpenGL = false;
632  bool stereoAnaglyph = false;
633  ACG::GLMatrixd projSave = glstate_->projection();
634  ACG::GLMatrixd projLR[2];
635 
636  if (properties_.stereo()) {
637  stereoOpenGL = OpenFlipper::Options::stereoMode () == OpenFlipper::Options::OpenGL && OpenFlipper::Options::glStereo ();
638  stereoAnaglyph = !stereoOpenGL;
640  }
641 
642  if (!stereoOpenGL && !stereoAnaglyph)
643  {
644  // setup render target fbo
646  properties_.multisampling() ? 16 : 0, -1);
647  }
648 
649 
650 
651  // Check if we use build in default renderer
652  if ( renderManager().activeId( properties_.viewerId() ) == 0 ) {
653  drawScene_mono();
654  } else {
655  RenderInterface* renderPlugin = renderManager().active( properties_.viewerId() )->plugin;
656 
657  // eventually set viewer id in IRenderer
658  ACG::IRenderer* shaderRenderPlugin = dynamic_cast<ACG::IRenderer*>(renderPlugin);
659 
660  if (shaderRenderPlugin)
661  shaderRenderPlugin->setViewerID( properties_.viewerId() );
662 
663  if (stereoOpenGL || stereoAnaglyph) {
664  // save current fbo
665  GLuint backbufferFbo = 0;
666  GLuint backbufferTarget = 0;
667  glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&backbufferFbo);
668  glGetIntegerv(GL_DRAW_BUFFER, (GLint*)&backbufferTarget);
669 
670  // setup stereo rendering
671 
672  // left eye: fbo 0
673  // right eye: fbo 1
674 
675  for (int eye = 0; eye < 2; ++eye) {
676 
677  glstate_->set_projection(projLR[eye]);
678  if (stereoOpenGL && !numPostProcessors) {
679  // render directly into back_left
680  glDrawBuffer(eye ? GL_BACK_RIGHT : GL_BACK_LEFT);
681  glEnable(GL_SCISSOR_TEST);
682  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
683  glDisable(GL_SCISSOR_TEST);
684  }
685  else {
687  properties_.multisampling() ? 16 : 0, eye);
688  }
689 
690  renderPlugin->render(glstate_,properties_);
691  drawCursor();
692  }
693 
694  // restore projection
695  glstate_->set_projection(projSave);
696 
697  // restore backbuffer
698  glBindFramebuffer(GL_FRAMEBUFFER, backbufferFbo);
699  glDrawBuffer(backbufferTarget);
700  }
701  else {
702  renderPlugin->render(glstate_,properties_);
703  drawCursor();
704  }
705  }
706  checkGLError();
707 
708 
709  // =================================================================================
710  // Post-Processing pipeline
711 
712 
714  glstate_,
715  glstate_->modelview(),
716  (stereoOpenGL || stereoAnaglyph) ? projLR[0] : glstate_->projection(),
717  projLR[1],
718  stereoOpenGL);
719 
720  if (stereoAnaglyph)
722 
723  // =================================================================================
724 
725  glDrawBuffer(backbufferTarget);
726 
727  // unbind vbo for qt log window
728  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER, 0);
729 
730  ACG::GLState::activeTexture(GL_TEXTURE0);
731  ACG::GLState::bindTexture(GL_TEXTURE_2D, 0);
732 
733 // fbo.release();
734 //
735 // QRect blitRect(0,0,glstate_->viewport_width(),glstate_->viewport_height());
736 //
737 // //
738 // //QTime time;
739 // //time.restart();
740 // QGLFramebufferObject::blitFramebuffer( 0 , blitRect, &fbo, blitRect , GL_COLOR_BUFFER_BIT );
741 // //std::cerr << "Elapsed for blit: " << time.elapsed() << std::endl;
742 
743  glFinish();
744 
745  frame_time_ = timer.elapsed();
746 
747 
748  // Inside the glWidget rendering, the system should not send extra updates
749  properties_.blockSignals(false);
750 
751 }
752 
753 
754 //-----------------------------------------------------------------------------
755 
756 
757 void glViewer::drawScene_mono()
758 {
759  if (sceneGraphRoot_) {
761  GLuint refBits = 0;
762  QSet<GLuint> references;
763 
764  if (oM)
765  {
766  glClear (GL_STENCIL_BUFFER_BIT);
767  ACG::GLState::enable (GL_STENCIL_TEST);
768  glStencilOp (GL_KEEP, GL_KEEP, GL_ZERO);
769  glStencilFunc (GL_ALWAYS, 0, ~0);
770 
772  o_it != PluginFunctions::objectsEnd(); ++o_it)
773  {
774  bool ok;
775  GLuint ref;
776 
777  ok = oM->stencilRefForObject(*o_it, ref);
778 
779  if (ok)
780  {
781  o_it->stencilRefNode ()->setReference (ref);
782  o_it->stencilRefNode ()->show ();
783  refBits |= ref;
784  references << ref;
785  }
786  else
787  o_it->stencilRefNode ()->hide ();
788  }
789  }
790 
791  // First pass
794 
795  // Second Pass for Blending operations
798 
799  if (oM)
800  {
801  if (oM->type() == ViewObjectMarker::PerBit)
802  {
803  references.clear ();
804  for (unsigned int i = 0; i < sizeof (GLuint) * 8; i++)
805  if (refBits & (1 << i))
806  references << (1 << i);
807  }
808 
809  glPushAttrib(GL_ALL_ATTRIB_BITS);
810 
811  ACG::GLState::enable(GL_BLEND);
812  ACG::GLState::disable(GL_DEPTH_TEST);
813  ACG::GLState::disable(GL_LIGHTING);
814  ACG::GLState::disable(GL_DITHER);
815 
816  int vp_l, vp_b, vp_w, vp_h;
817  glstate_->get_viewport (vp_l, vp_b, vp_w, vp_h);
818 
819  glMatrixMode(GL_PROJECTION);
820  glPushMatrix ();
821  glLoadIdentity();
822  glOrtho(0, vp_w, vp_h, 0, 0, 1.0);
823  glMatrixMode(GL_MODELVIEW);
824  glPushMatrix ();
825  glLoadIdentity();
826 
827  glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
828 
829  foreach (unsigned int ref, references)
830  {
831  bool ok;
832  GLenum sfactor;
833  GLenum dfactor;
834  ACG::Vec4f color;
835  unsigned int mask = ~0;
836 
837  if (oM->type() == ViewObjectMarker::PerBit)
838  {
839  ok = oM->blendForStencilRefBit (ref, sfactor, dfactor, color);
840  mask = ref;
841  }
842  else
843  ok = oM->blendForStencilRefNumber (ref, sfactor, dfactor, color);
844 
845  if (!ok)
846  continue;
847 
848  glStencilFunc (GL_EQUAL, ref, mask);
849 
850  ACG::GLState::blendFunc (sfactor, dfactor);
851  glColor4f (color[0], color [1], color [2], color[3]);
852 
853  glBegin (GL_QUADS);
854  glVertex2i(0, 0);
855  glVertex2i(0, vp_h);
856  glVertex2i(vp_w, vp_h);
857  glVertex2i(vp_w, 0);
858  glEnd ();
859 
860  }
861 
862  glMatrixMode(GL_PROJECTION);
863  glPopMatrix ();
864  glMatrixMode(GL_MODELVIEW);
865  glPopMatrix ();
866 
867  glPopAttrib ();
868  ACG::GLState::disable (GL_STENCIL_TEST);
869  }
870 
871 
872  }
873 
874  drawCursor();
875 
876 }
877 
878 
880 {
882  {
884  // reset view transformation
886  // translate cursor position to 0,0
888  // paint cursor
891  }
892 }
893 
894 
896 {
897  home_modelview_ = glstate_->modelview();
898  home_inverse_modelview_ = glstate_->inverse_modelview();
899  homeOrthoWidth_ = properties_.orthoWidth();
900  home_center_ = properties_.trackballCenter();
901  home_radius_ = properties_.trackballRadius();
902 }
903 
904 
906 {
907  makeCurrent();
908  glstate_->set_modelview(home_modelview_, home_inverse_modelview_);
909  properties_.orthoWidth( homeOrthoWidth_ );
910  properties_.trackballCenter( home_center_ );
911  properties_.trackballRadius(home_radius_);
913  updateGL();
914 
915  emit viewChanged();
916 
917 }
918 
919 //-----------------------------------------------------------------------------
920 
922 {
923  makeCurrent();
924 
925  // update scene graph (get new bounding box and set projection right, including near and far plane)
927 
928  unsigned int maxPases = 1;
929  ACG::Vec3d bbmin,bbmax;
930  // update scene bounding boxes
932 
933  // update scene properties (near, far plane, scene radius according to the computed bounding boxes)
934  sceneGraph ( PluginFunctions::getSceneGraphRootNode(), maxPases,bbmin,bbmax,true);
935 
936 
937  // update camera
938  // move center (in camera coords) to origin and translate in -z dir
940  - ACG::Vec3d(0.0, 0.0, 3.0 * properties_.sceneRadius()));
941 
943  double aspect = (double) glWidth() / (double) glHeight();
944  if (aspect > 1.0)
946 
949  updateGL();
950 
951  emit viewChanged();
952 
953 }
954 
955 
956 //-----------------------------------------------------------------------------
957 
958 
959 void glViewer::setView(const ACG::GLMatrixd& _modelview,
960  const ACG::GLMatrixd& _inverse_modelview)
961 {
962  makeCurrent();
963  glstate_->set_modelview(_modelview, _inverse_modelview);
964  updateGL();
965 
966  emit viewChanged();
967 }
968 
969 
970 //-----------------------------------------------------------------------------
971 
972 
974 {
975 
976  // lock update
978 
979  // init GL state
980  glstate_->initialize();
981 
982  // OpenGL state
983  ACG::GLState::enable(GL_DEPTH_TEST);
984  ACG::GLState::enable(GL_LIGHTING);
985  ACG::GLState::disable(GL_DITHER);
986  ACG::GLState::shadeModel( GL_FLAT );
987 
988 
989  projectionMode( projectionMode_ );
990  normalsMode( normalsMode_ );
991 
992  // Update all settings which would require a redraw
993  applyProperties();
994 
995  // modelview
996  glstate_->translate(0.0, 0.0, -3.0);
997  setHome();
998 
999 
1000  // pixel transfer
1001  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1002  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1003  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1004  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1005  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1006  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1007  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1008  glPixelStorei(GL_PACK_ALIGNMENT, 1);
1009 
1010 
1011  // unlock update (we started locked)
1013 
1014  initialized_ = true;
1015 
1016  if (sceneGraphRoot_)
1017  {
1018  unsigned int maxPases = 1;
1019  ACG::Vec3d bbmin,bbmax;
1020  ACG::SceneGraph::analyzeSceneGraph(sceneGraphRoot_,maxPases,bbmin,bbmax);
1021 
1022  sceneGraph ( sceneGraphRoot_, maxPases,bbmin,bbmax,true);
1023 
1024  viewAll();
1025  }
1026 }
1027 
1028 
1029 //-----------------------------------------------------------------------------
1030 
1031 
1032 void glViewer::paintGL(double _aspect)
1033 {
1034  if (!initialized_)
1035  initializeGL ();
1036 
1037  if (!properties_.updateLocked())
1038  {
1040 
1041  glPushAttrib (GL_ALL_ATTRIB_BITS);
1042 
1043  ACG::GLState::enable(GL_DEPTH_TEST);
1044  ACG::GLState::enable(GL_LIGHTING);
1045  ACG::GLState::disable(GL_DITHER);
1046  ACG::GLState::shadeModel( GL_FLAT );
1047 
1048  glMatrixMode(GL_PROJECTION);
1049  glPushMatrix();
1050 
1051  glMatrixMode(GL_MODELVIEW);
1052  glPushMatrix();
1053 
1054 
1055  normalsMode( normalsMode_ );
1056 
1057  applyProperties();
1058 
1059  glstate_->setState();
1060 
1061  glColor4f(1.0,0.0,0.0,1.0);
1062 
1063  glstate_->clearBuffers ();
1064 
1066 
1067  // draw scene
1068  drawScene(_aspect);
1069 
1070  glPopMatrix();
1071 
1072  glMatrixMode(GL_PROJECTION);
1073  glPopMatrix();
1074 
1075  glPopAttrib ();
1076  }
1077 
1078 }
1079 
1080 
1081 //-----------------------------------------------------------------------------
1082 
1083 
1084 void glViewer::resizeEvent(QGraphicsSceneResizeEvent *)
1085 {
1087  glstate_->viewport(scenePos().x(),
1088  scene()->height () - scenePos().y() - size().height (),
1089  size().width (), size().height (),
1090  scene()->width (), scene()->height ());
1091  update();
1092 
1093  emit viewChanged();
1094 }
1095 
1096 void glViewer::moveEvent (QGraphicsSceneMoveEvent *)
1097 {
1098  glstate_->viewport(scenePos().x(),
1099  scene()->height () - scenePos().y() - size().height (),
1100  size().width (), size().height (),
1101  scene()->width (), scene()->height ());
1102  update();
1103 
1104  emit viewChanged();
1105 }
1106 
1107 //-----------------------------------------------------------------------------
1108 
1109 void glViewer::encodeView(QString& _view, const QSize& _windowSize /*= QSize()*/,
1110  const int _splitterWidth /*=-1*/, const bool _make_c_string /*= false*/)
1111 {
1112  // Get current matrices
1113  const ACG::GLMatrixd m = glstate_->modelview();
1114  const ACG::GLMatrixd p = glstate_->projection();
1115 
1116  static const char *line_delim_c = " \\\n";
1117  static const char *line_delim_std = line_delim_c + 2;
1118  const char *line_delim = _make_c_string ? line_delim_c : line_delim_std;
1119 
1120  if (_make_c_string)
1121  _view += "\"";
1122 
1123  // Add modelview matrix to output
1124  _view += QString(COPY_PASTE_VIEW_START_STRING) + line_delim;
1125  _view += QString::number(m(0,0)) + " " + QString::number(m(0,1)) + " " + QString::number(m(0,2)) + " " + QString::number(m(0,3)) + line_delim;
1126  _view += QString::number(m(1,0)) + " " + QString::number(m(1,1)) + " " + QString::number(m(1,2)) + " " + QString::number(m(1,3)) + line_delim;
1127  _view += QString::number(m(2,0)) + " " + QString::number(m(2,1)) + " " + QString::number(m(2,2)) + " " + QString::number(m(2,3)) + line_delim;
1128  _view += QString::number(m(3,0)) + " " + QString::number(m(3,1)) + " " + QString::number(m(3,2)) + " " + QString::number(m(3,3)) + line_delim;
1129 
1130  // Add projection matrix to output
1131  _view += QString::number(p(0,0)) + " " + QString::number(p(0,1)) + " " + QString::number(p(0,2)) + " " + QString::number(p(0,3)) + line_delim;
1132  _view += QString::number(p(1,0)) + " " + QString::number(p(1,1)) + " " + QString::number(p(1,2)) + " " + QString::number(p(1,3)) + line_delim;
1133  _view += QString::number(p(2,0)) + " " + QString::number(p(2,1)) + " " + QString::number(p(2,2)) + " " + QString::number(p(2,3)) + line_delim;
1134  _view += QString::number(p(3,0)) + " " + QString::number(p(3,1)) + " " + QString::number(p(3,2)) + " " + QString::number(p(3,3)) + line_delim;
1135 
1136  // add gl width/height, current projection Mode and the ortho mode width to output
1137  _view += QString::number(_windowSize.width()) + " " + QString::number(_windowSize.height()) + " " + QString::number(_splitterWidth)+ " " + QString::number(projectionMode_) + " " + QString::number(properties_.orthoWidth()) + line_delim;;
1138 
1139  // Add viewer size
1140  _view += QString::fromUtf8("%1 %2").arg(size().width()).arg(size().height());
1141 
1142  if (_make_c_string)
1143  _view += "\"";
1144 
1145  _view += "\n";
1146 }
1147 
1148 
1149 //----------------------------------------------------------------------------
1150 
1151 
1152 bool glViewer::decodeView(const QString& _view,
1153  ACG::GLMatrixd &m, ACG::GLMatrixd &p, int &pMode, double &ortho_width,
1154  QSize *_windowSize /*= NULL*/,
1155  int* _splitterWidth /*= NULL*/, QSize *_viewportSize)
1156 {
1157  // Remove the magic from the string
1158  QString temp = _view;
1159  temp.remove(0,sizeof(COPY_PASTE_VIEW_START_STRING));
1160 
1161  //Split it into its components
1162  QStringList split = temp.split(QRegExp("[\\n\\s]"),QString::SkipEmptyParts);
1163 
1164  // New version
1165  if ( split.size() >= 37 ) {
1166 
1167  //*********************************************************
1168  // Parse the components
1169  // first, get the projection and the modelview matrices
1170  //*********************************************************
1171  for (std::size_t i = 0; i < 4; ++i)
1172  {
1173  for (std::size_t j = 0; j < 4; ++j)
1174  {
1175  m(i,j) = split[i*4 + j].toDouble();
1176  p(i,j) = split[i*4 + j +16].toDouble();
1177  }
1178  }
1179 
1180  //*********************************************************
1181  //parse the window size if requested
1182  //*********************************************************
1183  if (_windowSize)
1184  {
1185  //restore the old window size
1186  int w = split[32].toInt();
1187  int h = split[33].toInt();
1188  *_windowSize = QSize(w,h);
1189  }
1190 
1191  //*********************************************************
1192  //parse the splitter width for the toolboxes if requested
1193  //*********************************************************
1194  if (_splitterWidth) {
1195  *_splitterWidth = split[34].toInt();
1196  }
1197 
1198  //*********************************************************
1199  // Projection mode and orthogonal width
1200  //*********************************************************
1201  pMode = split[35].toInt();
1202  ortho_width = split[36].toDouble();
1203 
1204  if (_viewportSize && split.size() >= 39) {
1205  *_viewportSize = QSize(split[37].toInt(), split[38].toInt());
1206  }
1207 
1208  } else if ( split.size() == 36 ) { // Old Version
1209 
1210  //*********************************************************
1211  // Parse the components
1212  // first, get the projection and the modelview matrices
1213  //*********************************************************
1214  for (std::size_t i = 0; i < 4; ++i)
1215  {
1216  for (std::size_t j = 0; j < 4; ++j)
1217  {
1218  m(i,j) = split[i*4 + j].toDouble();
1219  p(i,j) = split[i*4 + j +16].toDouble();
1220  }
1221  }
1222 
1223  //*********************************************************
1224  //parse the window size if requested
1225  //*********************************************************
1226  if (_windowSize)
1227  {
1228  //restore the old window size
1229  int w = split[32].toInt();
1230  int h = split[33].toInt();
1231  *_windowSize = QSize(w,h);
1232  }
1233 
1234 
1235  //*********************************************************
1236  // Return -1 to inform, that the value is unknown
1237  //*********************************************************
1238  if (_splitterWidth) {
1239  *_splitterWidth = -1;
1240  }
1241 
1242  //*********************************************************
1243  // Projection mode and orthogonal width
1244  //*********************************************************
1245  pMode = split[34].toInt();
1246  ortho_width = split[35].toDouble();
1247 
1248  } else { // Garbage ?!
1249  std::cerr << "Unable to paste view ... wrong parameter count!! is" << split.size() << std::endl;
1250  return false;
1251  }
1252 
1253  return true;
1254 }
1255 
1256 bool glViewer::decodeView(const QString& _view, QSize *_windowSize /*= NULL*/,
1257  int* _splitterWidth /*= NULL*/, QSize *_viewportSize)
1258 {
1259  if (_view.left(sizeof(COPY_PASTE_VIEW_START_STRING)-1) != QString(COPY_PASTE_VIEW_START_STRING))
1260  {
1261  std::cerr << "No View was copied." << std::endl;
1262  return false;
1263  }
1264 
1265  ACG::GLMatrixd m, p;
1266  int pMode;
1267  double ortho_width;
1268 
1269  if (!decodeView(_view, m, p, pMode, ortho_width,
1270  _windowSize, _splitterWidth, _viewportSize))
1271  return false;
1272  properties_.orthoWidth(ortho_width);
1273 
1274  // Switch to our gl context
1275  makeCurrent();
1276 
1277  // set projection mode
1278  if (projectionMode_ != (ProjectionMode)pMode)
1280 
1281  // Apply new modelview matrix
1282  glstate_->set_modelview(m);
1283 
1284  updateGL();
1285 
1286  return true;
1287 }
1288 
1289 
1290 //-----------------------------------------------------------------------------
1291 
1292 
1293 void glViewer::actionCopyView(const QSize &_windowSize /*= QSize(-1,-1)*/, const int _splitterWidth /*= -1*/,
1294  const bool _make_c_string /*= false*/)
1295 {
1296  QString view;
1297  encodeView(view,_windowSize,_splitterWidth, _make_c_string);
1298  QApplication::clipboard()->setText(view);
1299 }
1300 
1301 
1302 //-----------------------------------------------------------------------------
1303 
1304 
1305 void glViewer::actionPasteView(QSize * _windowSize /*= NULL*/, int *_splitterWidth /*= NULL*/)
1306 {
1307  QString view;
1308  view = QApplication::clipboard()->text();
1309  decodeView(view,_windowSize,_splitterWidth);
1310 }
1311 
1312 void glViewer::actionSetView(QString view) {
1313  decodeView(view, 0, 0);
1314 }
1315 
1316 //-----------------------------------------------------------------------------
1317 
1318 void
1319 glViewer::createWidgets()
1320 {
1321  // Construct GL context & widget
1322 
1323  wheelZ_=new ACG::QtWidgets::QtWheel( 0,"wheel-z",ACG::QtWidgets::QtWheel::Vertical);
1324  wheelZ_->setMinimumSize(wheelZ_->sizeHint());
1325  wheelZ_->setMaximumSize(wheelZ_->sizeHint());
1326  connect(wheelZ_,SIGNAL(angleChangedBy(double)),
1327  this,SLOT(slotWheelZ(double)));
1328  wheelZ_->setToolTip( tr("Translate along <b>z-axis</b>."));
1329  wheelZ_->setWhatsThis( tr("Translate along <b>z-axis</b>."));
1330 
1331  wheelY_=new ACG::QtWidgets::QtWheel( 0,"wheel-y",ACG::QtWidgets::QtWheel::Horizontal);
1332  wheelY_->setMinimumSize(wheelY_->sizeHint());
1333  wheelY_->setMaximumSize(wheelY_->sizeHint());
1334  connect(wheelY_,SIGNAL(angleChangedBy(double)),
1335  this,SLOT(slotWheelY(double)));
1336  wheelY_->setToolTip(tr("Rotate around <b>y-axis</b>."));
1337  wheelY_->setWhatsThis( tr("Rotate around <b>y-axis</b>."));
1338 
1339  wheelX_=new ACG::QtWidgets::QtWheel( 0,"wheel-x" ,ACG::QtWidgets::QtWheel::Vertical);
1340  wheelX_->setMinimumSize(wheelX_->sizeHint());
1341  wheelX_->setMaximumSize(wheelX_->sizeHint());
1342  connect(wheelX_,SIGNAL(angleChangedBy(double)),
1343  this,SLOT(slotWheelX(double)));
1344  wheelX_->setToolTip(tr("Rotate around <b>x-axis</b>."));
1345  wheelX_->setWhatsThis( tr("Rotate around <b>x-axis</b>."));
1346 
1347  // Hide or show wheels (depending on ini option)
1348  if( ! OpenFlipperSettings().value("Core/Gui/glViewer/showControlWheels").toBool() )
1349  slotHideWheels();
1350 
1351  QGraphicsWidget *wheelX = glScene_->addWidget (wheelX_);
1352  QGraphicsWidget *wheelY = glScene_->addWidget (wheelY_);
1353  QGraphicsWidget *wheelZ = glScene_->addWidget (wheelZ_);
1354 
1355  wheelX_->setWindowOpacity (0.5);
1356  wheelY_->setWindowOpacity (0.5);
1357  wheelZ_->setWindowOpacity (0.5);
1358 
1359  wheelX->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
1360  wheelY->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
1361  wheelZ->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
1362 
1363  glBaseLayout_ = new QtGLViewerLayout;
1364  glBaseLayout_->addWheelX(wheelX);
1365  glBaseLayout_->addWheelY(wheelY);
1366  glBaseLayout_->addWheelZ(wheelZ);
1367 
1368  connect(wheelX_,SIGNAL(hideWheel()),this,SLOT(slotHideWheels()));
1369  connect(wheelY_,SIGNAL(hideWheel()),this,SLOT(slotHideWheels()));
1370  connect(wheelZ_,SIGNAL(hideWheel()),this,SLOT(slotHideWheels()));
1371 
1372  setLayout(glBaseLayout_);
1373 }
1374 
1375 //-----------------------------------------------------------------------------
1376 
1377 
1378 void glViewer::translate(const ACG::Vec3d& _trans)
1379 {
1380  makeCurrent();
1381  glstate_->translate(_trans[0], _trans[1], _trans[2], ACG::MULT_FROM_LEFT);
1382 
1383  updateGL();
1384 
1385  emit viewChanged();
1386 }
1387 
1388 
1389 //-----------------------------------------------------------------------------
1390 
1391 
1393 {
1394  makeCurrent();
1396 }
1397 
1398 
1399 //-----------------------------------------------------------------------------
1400 
1401 
1402 void glViewer::rotate(const ACG::Vec3d& _axis,
1403  double _angle,
1404  const ACG::Vec3d& _center)
1405 {
1406  makeCurrent();
1407  ACG::Vec3d t = glstate_->modelview().transform_point(_center);
1408  glstate_->translate(-t[0], -t[1], -t[2], ACG::MULT_FROM_LEFT);
1409  glstate_->rotate(_angle, _axis[0], _axis[1], _axis[2], ACG::MULT_FROM_LEFT);
1410  glstate_->translate( t[0], t[1], t[2], ACG::MULT_FROM_LEFT);
1411 
1412  updateGL();
1413 
1414  emit viewChanged();
1415 }
1416 
1417 
1418 //-----------------------------------------------------------------------------
1419 
1420 
1421 unsigned int glViewer::glWidth() const {
1422  return size().width();
1423 }
1424 unsigned int glViewer::glHeight() const {
1425  return size().height();
1426 }
1427 QSize glViewer::glSize() const {
1428  return QSize(size().width(),size().height());
1429 }
1430 QPoint glViewer::glMapFromGlobal( const QPoint& _pos ) const {
1431  QPoint p (scene()->views().front()->mapFromGlobal(_pos));
1432  QPointF f (mapFromScene(QPointF(p.x(), p.y ())));
1433  return QPoint (f.x(), f.y());
1434 }
1435 
1436 QPoint glViewer::glMapToGlobal( const QPoint& _pos ) const {
1437  QPointF f (mapToScene(QPointF(_pos.x(), _pos.y ())));
1438  QPoint p (f.x(), f.y());
1439  return scene()->views().front()->mapToGlobal(p);
1440 }
1441 
1442 double glViewer::field_of_view_vertical() const {
1443  return OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble()
1444  + fovyModifier_;
1445 }
1446 
1447 
1448 //-----------------------------------------------------------------------------
1449 
1450 
1451 void glViewer::slotWheelX(double _dAngle)
1452 {
1454  updateGL();
1455 
1456  emit viewChanged();
1457 }
1458 
1459 void glViewer::slotWheelY(double _dAngle)
1460 {
1462  updateGL();
1463 
1464  emit viewChanged();
1465 }
1466 
1467 void glViewer::slotWheelZ(double _dist)
1468 {
1469  double dz = _dist * 0.5 / M_PI * properties_.sceneRadius() * 2.0;
1470  translate(ACG::Vec3d(0,0,dz));
1471  updateGL();
1472 
1473  emit viewChanged();
1474 }
1475 
1476 //-----------------------------------------------------------------------------
1477 
1478 
1480 {
1481  glareaGrabbed_ = true;
1482 
1483  if (properties_.cursorPainter()) {
1484  properties_.cursorPainter()->setCursor(Qt::BlankCursor);
1485  std::cerr << "grabGLArea: Blanking cursorpainter cursor" << std::endl;
1486  } else {
1487  setCursor(Qt::BlankCursor);
1488  std::cerr << "grabGLArea: Blanking qt cursor" << std::endl;
1489  }
1490  grabMouse();
1491  grabKeyboard();
1492 }
1493 
1495 {
1496  glareaGrabbed_ = false;
1497 
1498  ungrabMouse();
1499  ungrabKeyboard();
1500 
1501  if (properties_.cursorPainter()) {
1502  properties_.cursorPainter()->setCursor(Qt::ArrowCursor);
1503  std::cerr << "grabGLArea: Setting cursorPainter cursor to arrow" << std::endl;
1504  } else {
1505  setCursor(Qt::ArrowCursor);
1506  std::cerr << "grabGLArea: Setting qt cursor to arrow" << std::endl;
1507  }
1508 }
1509 
1510 
1511 //-----------------------------------------------------------------------------
1512 
1513 
1514 void glViewer::contextMenuEvent(QGraphicsSceneContextMenuEvent* _e)
1515 {
1516  emit signalMakeActive();
1517  glScene_->update ();
1518 
1519  QPoint p (_e->pos().x(), _e->pos().y());
1521 }
1522 
1523 
1524 //-----------------------------------------------------------------------------
1525 
1526 void glViewer::mousePressEvent(QGraphicsSceneMouseEvent* _e)
1527 {
1528  QPoint p (_e->scenePos().x(), _e->scenePos().y());
1529  QMouseEvent me(QEvent::MouseButtonPress ,p, _e->screenPos(), _e->button(),
1530  _e->buttons(), _e->modifiers());
1531  _e->accept ();
1532 
1533  emit signalMakeActive();
1534  glScene_->update ();
1535 
1536  // right button pressed => popup menu (ignore here)
1537  if (allowConstrainedRotation() || _e->button() != Qt::RightButton )
1538  {
1539  switch (properties_.actionMode())
1540  {
1541  case Viewer::ExamineMode:
1542  if ((_e->modifiers() & Qt::ControlModifier)) // drag&drop
1543  emit startDragEvent( &me );
1544  else
1545  viewMouseEvent(&me); // examine
1546 
1547  if (clickTimer_.isActive ())
1548  {
1549  clickTime_ = QTime ();
1550  clickTimer_.stop ();
1551  }
1552  else
1553  {
1554  clickTime_.start ();
1555  clickEvent_ = me;
1556  }
1557  break;
1558 
1559  case Viewer::LightMode:
1560  emit(signalMouseEventLight(&me));
1561  break;
1562 
1563  case Viewer::PickingMode: // give event to application
1564  emit(signalMouseEvent(&me, properties_.pickMode() ));
1565  emit(signalMouseEvent(&me));
1566  break;
1567 
1568  case Viewer::QuestionMode: // give event to application
1569  emit(signalMouseEventIdentify(&me));
1570  break;
1571  }
1572  }
1573 }
1574 
1575 
1576 //-----------------------------------------------------------------------------
1577 
1578 
1579 void glViewer::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* _e)
1580 {
1581  QPoint p (_e->scenePos().x(), _e->scenePos().y());
1582  QMouseEvent me(QEvent::MouseButtonDblClick ,p, _e->screenPos(), _e->button(),
1583  _e->buttons(), _e->modifiers());
1584  _e->accept ();
1585 
1586  emit signalMakeActive();
1587  glScene_->update ();
1588 
1589  switch (properties_.actionMode())
1590  {
1591  case Viewer::ExamineMode:
1592  viewMouseEvent(&me);
1593  emit signalMouseEventClick (&me, true);
1594  break;
1595 
1596  case Viewer::LightMode:
1597  emit(signalMouseEventLight(&me));
1598  break;
1599 
1600  case Viewer::PickingMode: // give event to application
1601  emit(signalMouseEvent(&me, properties_.pickMode() ));
1602  emit(signalMouseEvent(&me));
1603  break;
1604 
1605  case Viewer::QuestionMode: // give event to application
1606  emit(signalMouseEventIdentify(&me));
1607  break;
1608  }
1609 }
1610 
1611 
1612 //-----------------------------------------------------------------------------
1613 
1614 
1615 void glViewer::mouseMoveEvent(QGraphicsSceneMouseEvent* _e)
1616 {
1617  QPoint p (_e->scenePos().x(), _e->scenePos().y());
1618  QMouseEvent me(QEvent::MouseMove ,p, _e->screenPos(), _e->button(),
1619  _e->buttons(), _e->modifiers());
1620  _e->accept();
1621 
1622  switch ( properties_.actionMode() )
1623  {
1624  case Viewer::ExamineMode:
1625  viewMouseEvent(&me);
1626  break;
1627 
1628  case Viewer::LightMode:
1629  emit(signalMouseEventLight(&me));
1630  break;
1631 
1632  case Viewer::PickingMode:
1633  // give event to application
1634  // deliver mouse moves with no button down, if tracking is enabled,
1635  if ((_e->buttons() & (Qt::LeftButton | Qt::MidButton | Qt::RightButton))
1636  || trackMouse_)
1637  {
1638  emit(signalMouseEvent(&me, properties_.pickMode() ));
1639  emit(signalMouseEvent(&me));
1640  }
1641  break;
1642 
1643  case Viewer::QuestionMode: // give event to application
1644  emit(signalMouseEventIdentify(&me));
1645  break;
1646 
1647  default: // avoid warning
1648  break;
1649  }
1650 }
1651 
1652 //-----------------------------------------------------------------------------
1653 
1654 
1655 void glViewer::mouseReleaseEvent(QGraphicsSceneMouseEvent* _e)
1656 {
1657  QPoint p (_e->scenePos().x(), _e->scenePos().y());
1658  QMouseEvent me(QEvent::MouseButtonRelease ,p, _e->screenPos(), _e->button(),
1659  _e->buttons(), _e->modifiers());
1660  _e->accept();
1661 
1662 // if (_event->button() == Qt::RightButton )
1663 // hidePopupMenus();
1664 
1665  if (_e->button() != Qt::RightButton || (properties_.actionMode() == Viewer::PickingMode) )
1666  {
1667  switch ( properties_.actionMode() )
1668  {
1669  case Viewer::ExamineMode:
1670  viewMouseEvent(&me);
1671 
1672  if (!clickTime_.isNull ())
1673  {
1674  int elapsed = clickTime_.elapsed ();
1675  QPoint diff = clickEvent_.pos () - me.pos ();
1676 
1677  if (abs (diff.x ()) <= 1 && abs (diff.y ()) <= 1 && elapsed <= QApplication::doubleClickInterval () / 2)
1678  {
1679  clickTimer_.setSingleShot (true);
1680  clickTimer_.setInterval (QApplication::doubleClickInterval () - elapsed);
1681  clickTimer_.start ();
1682  }
1683  else
1684  {
1685  clickTime_ = QTime ();
1686  clickTimer_.stop ();
1687  }
1688  }
1689  break;
1690 
1691  case Viewer::LightMode:
1692  emit(signalMouseEventLight(&me));
1693  break;
1694 
1695  case Viewer::PickingMode: // give event to application
1696  emit(signalMouseEvent(&me, properties_.pickMode() ));
1697  emit(signalMouseEvent(&me));
1698  break;
1699 
1700  case Viewer::QuestionMode: // give event to application
1701  emit(signalMouseEventIdentify(&me));
1702  break;
1703 
1704  default: // avoid warning
1705  break;
1706  }
1707  }
1708 
1709  isRotating_ = false;
1710 }
1711 
1712 
1713 //-----------------------------------------------------------------------------
1714 
1715 
1716 void glViewer::wheelEvent(QGraphicsSceneWheelEvent* _e)
1717 {
1718  QPoint p (_e->scenePos().x(), _e->scenePos().y());
1719  QWheelEvent we(p, _e->screenPos(), _e->delta(), _e->buttons(),
1720  _e->modifiers(), _e->orientation());
1721  _e->accept();
1722 
1723  switch ( properties_.actionMode() )
1724  {
1725  case Viewer::ExamineMode:
1726  viewWheelEvent(&we);
1727  break;
1728 
1729  case Viewer::PickingMode: // give event to application
1730  emit(signalWheelEvent(&we, properties_.pickMode() ));
1731  break;
1732 
1733  default: // avoid warning
1734  break;
1735  }
1736 
1737  isRotating_ = false;
1738 }
1739 
1740 //-----------------------------------------------------------------------------
1741 
1742 void glViewer::dragEnterEvent(QGraphicsSceneDragDropEvent* _e)
1743 {
1744  std::cerr << "dragEnter" << std::endl;
1745 
1746  QPoint p (_e->pos().x(), _e->pos().y());
1747  QDragEnterEvent de(p, _e->possibleActions(), _e->mimeData(), _e->buttons(),
1748  _e->modifiers ());
1749  emit dragEnterEvent(&de);
1750  _e->accept();
1751 }
1752 
1753 //-----------------------------------------------------------------------------
1754 
1755 
1756 void glViewer::dropEvent(QGraphicsSceneDragDropEvent* _e)
1757 {
1758  std::cerr << "drop" << std::endl;
1759 
1760  QPoint p (_e->pos().x(), _e->pos().y());
1761  QDropEvent de(p, _e->possibleActions(), _e->mimeData(), _e->buttons(),
1762  _e->modifiers ());
1763  emit dropEvent(&de);
1764  _e->accept();
1765 }
1766 
1767 //-----------------------------------------------------------------------------
1768 
1769 
1770 void glViewer::viewMouseEvent(QMouseEvent* _event) {
1771 
1772  if (navigationMode_ == NORMAL_NAVIGATION) {
1773 
1774  handleNormalNavigation(_event);
1775 
1776  } else if (navigationMode_ == FIRSTPERSON_NAVIGATION) {
1777 
1779  }
1780 
1781 }
1782 
1783 //----------------------------------------------------------------------------
1784 
1785 void glViewer::handleFirstPersonNavigation( QMouseEvent* _event) {
1786 
1787  // Ego-shooter navigation mode is selected
1788  QPointF f(mapFromScene(QPointF(_event->pos().x(), _event->pos().y())));
1789  QPoint pos(f.x(), f.y());
1790 
1791  switch (_event->type()) {
1792 
1793  case QEvent::MouseButtonPress: {
1794  lastPoint2D_ = pos;
1795  lookAround_ = true;
1796  break;
1797  }
1798 
1799  case QEvent::MouseButtonDblClick: {
1800  flyTo(_event->pos(), _event->button() == Qt::MidButton);
1801  break;
1802  }
1803 
1804  case QEvent::MouseMove: {
1805 
1806  if(!lookAround_) break;
1807 
1808  // Considering center point of screen as origin
1809  QPoint newpos = QPoint(pos.x() - glWidth() / 2, glHeight() / 2 - pos.y());
1810  QPoint oldpos = QPoint(lastPoint2D_.x() - glWidth() / 2, glHeight() / 2 - lastPoint2D_.y());
1811 
1812  double x = 2.0 * newpos.x() / glWidth();
1813  double y = 2.0 * newpos.y() / glHeight();
1814 
1815  double xo = 2.0 * oldpos.x() / glWidth();
1816  double yo = 2.0 * oldpos.y() / glHeight();
1817 
1818  double diffx = xo - x;
1819  double diffy = yo - y;
1820 
1823 
1824  rotate(yaxis, -diffx * 90, glstate_->eye());
1825  rotate(xaxis, diffy * 90, glstate_->eye());
1826 
1827  lastPoint2D_ = pos;
1828 
1829  updateGL();
1830  lastMoveTime_.restart();
1831 
1832  emit viewChanged();
1833 
1834  break;
1835  }
1836 
1837  case QEvent::MouseButtonRelease: {
1838  lookAround_ = false;
1839  break;
1840  }
1841 
1842  default: // avoid warning
1843  break;
1844  }
1845 }
1846 
1847 //----------------------------------------------------------------------------
1848 
1849 void glViewer::handleNormalNavigation( QMouseEvent* _event ) {
1850 
1851  // Normal navigation mode is selected
1852  QPointF f(mapFromScene(QPointF(_event->pos().x(), _event->pos().y())));
1853  QPoint pos(f.x(), f.y());
1854 
1855  switch (_event->type()) {
1856 
1857  case QEvent::MouseButtonPress: {
1858 
1859  // Get the depth at the current mouse position ( projected )
1860  // This is used to do the translation in world coordinates
1861  // As the scene is rendered, we can get the depth directly from the framebuffer.
1862  GLfloat depth[1];
1863  GLint x2d = f.x() - scenePos().x();
1864  GLint y2d = glHeight() - (f.y() - scenePos().y());
1865  glReadPixels (x2d, y2d, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, depth);
1866  startDepth_ = depth[0];
1867 
1868  // shift key -> set rotation center
1869  if (_event->modifiers() & Qt::ShiftModifier) {
1870  ACG::Vec3d c;
1871  if (fast_pick(pos, c)) {
1873  properties_.trackballRadius( std::max(properties_.sceneRadius(), (c - glstate_->eye()).norm() * 0.9f) );
1874  }
1875  }
1876 
1878  lastPoint2D_ = pos;
1879  isRotating_ = true;
1880  timer_->stop();
1881 
1882  break;
1883  }
1884 
1885  case QEvent::MouseButtonDblClick: {
1886  flyTo(_event->pos(), _event->button() == Qt::MidButton);
1887  break;
1888  }
1889 
1890  case QEvent::MouseMove: {
1891  double factor = 1.0;
1892 
1893  if (_event->modifiers() == Qt::ShiftModifier)
1894  factor = properties_.wheelZoomFactorShift();
1895 
1896  // mouse button should be pressed
1897  if (_event->buttons() & (Qt::LeftButton | Qt::MidButton | Qt::RightButton)) {
1898  QPoint newPoint2D = pos;
1899 
1900  ACG::Vec3d newPoint3D;
1901  bool newPoint_hitSphere = mapToSphere(newPoint2D, newPoint3D);
1902 
1903  makeCurrent();
1904 
1905  // Left and middle button are pressed:
1906  // Translate along image planes normal direction -> zoom
1907  if ((_event->buttons() & Qt::LeftButton) && (_event->buttons() & Qt::MidButton)) {
1908  switch (projectionMode()) {
1909  case PERSPECTIVE_PROJECTION: {
1910  double value_y = properties_.sceneRadius() * ((newPoint2D.y() - lastPoint2D_.y())) * 3.0 / (double) glHeight();
1911  translate(ACG::Vec3d(0.0, 0.0, value_y * factor));
1912  updateGL();
1913  emit viewChanged();
1914  break;
1915  }
1916 
1917  case ORTHOGRAPHIC_PROJECTION: {
1918  double value_y = ((newPoint2D.y() - lastPoint2D_.y())) * properties_.orthoWidth() / (double) glHeight();
1919  properties_.orthoWidth( properties_.orthoWidth() - value_y * factor );
1921  updateGL();
1922  emit viewChanged();
1923  break;
1924  }
1925  }
1926  }
1927 
1928  // Middle button is pressed or if rotation is locked, left button can also be used
1929  // translation parallel to image plane
1930  // If an object was hit when the user started the translation,
1931  // the depth to the object is used to calculate the right translation vectors
1932  // such that the hitpoint stays below the mouse.
1933  else if ((_event->buttons() & Qt::MidButton) || (!allowRotation_ && (_event->buttons() & Qt::LeftButton)) ) {
1934 
1935  ACG::Vec3d translation;
1936 
1937 
1938  // if start depth is 1, no object was hit when starting translation
1939  if ( startDepth_ == 1 && projectionMode() != ORTHOGRAPHIC_PROJECTION ) {
1940  double value_x = properties_.sceneRadius() * ((newPoint2D.x() - lastPoint2D_.x())) * 2.0 / (double) glWidth();
1941  double value_y = properties_.sceneRadius() * ((newPoint2D.y() - lastPoint2D_.y())) * 2.0 / (double) glHeight();
1942  translation = ACG::Vec3d(value_x * factor, -value_y * factor, 0.0);
1943 
1944  } else {
1945  // Get the new mouse position in GL coordinates
1946  GLint x2dEnd = newPoint2D.x() - scenePos().x();
1947  GLint y2dEnd = glHeight() - (newPoint2D.y() - scenePos().y());
1948 
1949  // Get the last mouse position in GL coordinates
1950  GLint x2dStart = lastPoint2D_.x() - scenePos().x();
1951  GLint y2dStart = glHeight() - (lastPoint2D_.y() - scenePos().y());
1952 
1953  // unproject both to get translation vector
1954  ACG::Vec3d projectedStart(float(x2dStart),float(y2dStart),startDepth_);
1955  ACG::Vec3d projectedEnd(float(x2dEnd),float(y2dEnd),startDepth_);
1956  ACG::Vec3d unprojectedStart = glstate_->unproject(projectedStart);
1957  ACG::Vec3d unprojectedEnd = glstate_->unproject(projectedEnd);
1958 
1959  // calculate the difference and transform it with the modelview to get the right translation
1960  translation = unprojectedEnd - unprojectedStart;
1961  translation = glstate_->modelview().transform_vector(translation);
1962  }
1963 
1964  translate(translation);
1965 
1966  // left button pressed:
1967  // rotate the scene if rotation is not locked
1968  } else if (allowRotation_ && (_event->buttons() & Qt::LeftButton)) {
1969  ACG::Vec3d axis(1.0, 0.0, 0.0);
1970  double angle(0.0);
1971 
1972  if (lastPoint_hitSphere_) {
1973 
1974  if ((newPoint_hitSphere = mapToSphere(newPoint2D, newPoint3D))) {
1975  axis = lastPoint3D_ % newPoint3D;
1976  double cos_angle = (lastPoint3D_ | newPoint3D);
1977  if (fabs(cos_angle) < 1.0) {
1978  angle = acos(cos_angle) * 180.0 / M_PI * factor;
1979  angle *= 2.0; // inventor rotation
1980  }
1981  }
1982 
1983  rotate(axis, angle);
1984 
1985  }
1986 
1987  lastRotationAxis_ = axis;
1988  lastRotationAngle_ = angle;
1989  } else if (allowConstrainedRotation() && (_event->buttons() & Qt::RightButton)) {
1990  //ACG::Vec3d axis(constrainedRotationAxis_);
1991  //double angle(0.0);
1992 
1993  if (lastPoint_hitSphere_) {
1994 
1995  const QPoint dragVector = newPoint2D - lastPoint2D_;
1996  const double dragLength = dragVector.y();
1997  //ACG::Vec2d(dragVector.x(), dragVector.y()).norm();
1998  const double angle = -dragLength * factor;
1999 
2000  /*
2001  {
2002  makeCurrent();
2003  const ACG::Vec3d center =
2004  properties_.trackballCenter();
2005  const ACG::Vec3d t =
2006  startViewMatrix_.transform_point(center);
2007  glstate_->set_modelview(startViewMatrix_);
2008  glstate_->translate(-t[0], -t[1], -t[2],
2009  ACG::MULT_FROM_LEFT);
2010  glstate_->rotate(angle,
2011  constrainedRotationAxis_[0],
2012  constrainedRotationAxis_[1],
2013  constrainedRotationAxis_[2],
2014  ACG::MULT_FROM_LEFT);
2015  glstate_->translate(t[0], t[1], t[2],
2016  ACG::MULT_FROM_LEFT);
2017  }
2018  */
2019  ACG::Vec3d center(glWidth()/2.0, glHeight()/2.0, 0);
2020  rotate(constrainedRotationAxis_, angle, unproject(center));
2021 
2023  lastRotationAngle_ = angle;
2024  }
2025  }
2026 
2027  lastPoint2D_ = newPoint2D;
2028  lastPoint3D_ = newPoint3D;
2029  lastPoint_hitSphere_ = newPoint_hitSphere;
2030 
2031  updateGL();
2032  lastMoveTime_.restart();
2033  emit viewChanged();
2034  }
2035  break;
2036  }
2037 
2038  case QEvent::MouseButtonRelease: {
2039  lastPoint_hitSphere_ = false;
2040 
2041  // continue rotation ?
2042  if (isRotating_ && (_event->button() == Qt::LeftButton) && (!(_event->buttons() & Qt::MidButton))
2043  && (lastMoveTime_.elapsed() < 50) && properties_.animation())
2044  timer_->start(0);
2045  break;
2046  }
2047 
2048  default: // avoid warning
2049  break;
2050  }
2051 }
2052 
2053 //-----------------------------------------------------------------------------
2054 
2055 void glViewer::viewWheelEvent( QWheelEvent* _event)
2056 {
2057 
2058  // Default mouse wheel factor
2059  double factor = properties_.wheelZoomFactor();
2060 
2061  // Shift pressed, so we use the smaller factor
2062  if (_event->modifiers() == Qt::ShiftModifier)
2063  factor = properties_.wheelZoomFactorShift();
2064 
2065  // Mouse wheel inversion
2066  if (properties_.wheelInvert())
2067  factor *= -1.0;
2068 
2070  {
2071 
2072  // Control key : Modify field of view. Otherwise translate
2073  if ( _event->modifiers() & Qt::ControlModifier ) {
2074 
2075  // Most mouse types work in steps of 15 degrees, in which case the delta value is a
2076  // multiple of 120; i.e., 120 units * 1/8 = 15 degrees
2077  double numDegrees = double(_event->delta()) / 8.0;
2078  double numSteps = numDegrees / 15.0;
2079 
2080  // Update the fovy modifier
2081  // This modifier will be added to the default fov to get the zoom
2082  fovyModifier_ += numSteps * factor ;
2083 
2084  // Clamp to minimum
2085  if ( (OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble() + fovyModifier_) < 1.0 )
2086  fovyModifier_ = 1.0 -OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble();
2087 
2088  // Clamp to maximum
2089  if ( (OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble() + fovyModifier_) > 179.0 )
2090  fovyModifier_ = 179.0-OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble();
2091  } else {
2092 
2093 
2094  // Old style zoom (bad as it does not modify the projection but the modelview,
2095  // which kills e.g. Sky Boxes
2096  double d = -(double)_event->delta() / 120.0 * 0.2 * factor * properties_.trackballRadius() / 3.0;
2097  translate( ACG::Vec3d(0.0, 0.0, d) );
2098  }
2099 
2100 
2101 
2102  updateGL();
2103  }
2104  else
2105  {
2106  double d = (double)_event->delta() / 120.0 * 0.2 * factor * properties_.orthoWidth();
2108 
2109 
2111  updateGL();
2112  }
2113 
2114  emit viewChanged();
2115 }
2116 
2117 
2118 //-----------------------------------------------------------------------------
2119 
2120 
2121 bool glViewer::mapToSphere(const QPoint& _v2D, ACG::Vec3d& _v3D) const
2122 {
2123  if ( (_v2D.x() >= 0) && (_v2D.x() < (int)glWidth()) &&
2124  (_v2D.y() >= 0) && (_v2D.y() < (int)glHeight()) )
2125  {
2126  double x = (double)(_v2D.x() - ((double)glWidth() / 2.0)) / (double)glWidth();
2127  double y = (double)(((double)glHeight() / 2.0) - _v2D.y()) / (double)glHeight();
2128  double sinx = sin(M_PI * x * 0.5);
2129  double siny = sin(M_PI * y * 0.5);
2130  double sinx2siny2 = sinx * sinx + siny * siny;
2131 
2132  _v3D[0] = sinx;
2133  _v3D[1] = siny;
2134  _v3D[2] = sinx2siny2 < 1.0 ? sqrt(1.0 - sinx2siny2) : 0.0;
2135 
2136  return true;
2137  }
2138  else return false;
2139 }
2140 
2141 
2142 //-----------------------------------------------------------------------------
2143 
2144 
2146 {
2147  makeCurrent();
2149  updateGL();
2150 
2151  if (!properties_.updateLocked()) {
2152 
2153  static int msecs=0, count=0;
2154 
2155  msecs += frame_time_;
2156  if (count >= 10 && msecs >= 500) {
2157  char s[100];
2158  sprintf( s, "%.3f fps", (1000.0 * count / (float)msecs) );
2159  emit statusMessage(s,2000);
2160  count = msecs = 0;
2161  }
2162  else
2163  ++count;
2164  }
2165 }
2166 
2168 
2170 
2172 
2174 
2175  if (properties_.isCCWFront() )
2176  glFrontFace( GL_CCW );
2177  else
2178  glFrontFace( GL_CW );
2179 
2180  if ( properties_.backFaceCulling() )
2181  ACG::GLState::enable( GL_CULL_FACE );
2182  else
2183  ACG::GLState::disable( GL_CULL_FACE );
2184 
2185  // Make sure the right buffer is used in non stereo setup
2186  makeCurrent();
2187  ACG::GLState::drawBuffer(ACG::GLState::getFramebufferDraw() ? GL_COLOR_ATTACHMENT0 : GL_BACK);
2188 
2189  // Required for stereo toggling
2191 }
2192 
2194  makeCurrent();
2195  applyProperties();
2196  updateGL();
2197 }
2198 
2199 void glViewer::snapshot(QImage& _image, int _width, int _height, bool _alpha, bool _hideCoordsys, int samples) {
2200 
2201  int w = 0, h = 0, bak_w = 0, bak_h = 0, left = 0, bottom = 0;
2202 
2205 
2206  // Get viewport data
2207  glstate_->get_viewport(left, bottom, w, h);
2208  double aspect = (double)w / (double)h;
2209 
2210  // Test if size is given:
2211  if(_width != 0 || _height != 0) {
2212 
2213  // Adapt dimensions if aspect ratio is demanded
2214  if(_width == 0) {
2215  _width = (int)((double)_height * aspect);
2216  }
2217  if(_height == 0) {
2218  _height = (int)((double)_width / aspect);
2219  }
2220  bak_w = w;
2221  bak_h = h;
2222  w = _width;
2223  h = _height;
2224 
2225  // Set new viewport
2226  glstate_->viewport(0, 0, w, h);
2227  aspect = (double)w / (double)h;
2228  }
2229 
2230  QFramebufferObjectFormat format;
2231  format.setInternalTextureFormat(GL_RGBA);
2232  format.setTextureTarget(GL_TEXTURE_2D);
2233  // set the attachments as in the standard rendering
2234  format.setAttachment(QFramebufferObject::CombinedDepthStencil);
2235 // format.setAttachment(QFramebufferObject::CombinedDepthStencil);
2236  // 16 samples per pixel as we want a nice snapshot. If this is not supported
2237  // it will fall back to the maximal supported number of samples
2238  format.setSamples(samples);
2239 
2240  makeCurrent();
2241  QFramebufferObject fb(w,h,format);
2242 
2243  if ( fb.isValid() ){
2244 
2245  const GLuint prevFbo = ACG::GLState::getFramebufferDraw();
2246 
2247  ACG::GLState::bindFramebuffer(GL_FRAMEBUFFER_EXT, fb.handle());
2248 
2249  // Turn alpha on if demanded
2250  ACG::Vec4f backColorBak;
2251  ACG::Vec4f newBack;
2252 
2253  bool formerCoordsysState = true;
2254  // Hide coordsys node if demanded
2255  if(_hideCoordsys) {
2256  // Find coordsys node
2257  ACG::SceneGraph::BaseNode* node = 0;
2258  node = sceneGraphRoot_->find("Core Coordsys Node");
2259  if(node != 0) {
2260  formerCoordsysState = node->visible();
2261  node->hide();
2262  } else {
2263  emit statusMessage(QString(tr("Could not find coordsys node, thus it will appear in the snapshot anyway.")));
2264  }
2265  }
2266 
2267  backColorBak = properties()->backgroundColor();
2268 
2269  newBack = ACG::Vec4f(backColorBak[0], backColorBak[1], backColorBak[2], (_alpha ? 0.0f : 1.0f));
2270  properties()->backgroundColor(newBack);
2271 
2272  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2273 
2274  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2275 
2276  // adjust blend function for alpha channel
2277  ACG::GLState::blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE);
2279 
2280  glEnable(GL_MULTISAMPLE);
2281  paintGL(aspect);
2282  glFinish();
2283 
2285 
2286  glDisable(GL_MULTISAMPLE);
2287 
2288  //Qt FrameBuffer "toImage" function returns QImage::Format_ARGB32_Premultiplied. not desired
2289  QFramebufferObjectFormat tempFormat;
2290  tempFormat.setInternalTextureFormat(GL_RGBA);
2291  tempFormat.setTextureTarget(GL_TEXTURE_2D);
2292  QFramebufferObject temp(w,h, tempFormat);
2293  if (format.samples() != 0)
2294  {
2295  //cannot directly read from a multisampled framebuffer.
2296  //create new one without sampling and read from it
2297  QRect rect(QPoint(0, 0), QSize(w,h));
2298 
2299  QFramebufferObject::blitFramebuffer(&temp, rect, &fb, rect);
2300  ACG::GLState::bindFramebuffer(GL_FRAMEBUFFER_EXT, temp.handle());
2301  }
2302 
2303  //get the framebuffer data
2304  _image = QImage(w,h,QImage::Format_ARGB32);
2305  glReadPixels(0,0,w,h,GL_BGRA,GL_UNSIGNED_INT_8_8_8_8_REV,reinterpret_cast<void*>(_image.bits()));
2306  _image = _image.mirrored(false,true);//convert from opengl to qt coordinates
2307 
2308 
2309  //cleanup
2310  ACG::GLState::bindFramebuffer(GL_FRAMEBUFFER_EXT, prevFbo);
2311 
2312  // Reset alpha settings
2313  if(_alpha)
2314  properties()->backgroundColor(backColorBak);
2315 
2316  if(_hideCoordsys) {
2317  // Find coordsys node
2318  ACG::SceneGraph::BaseNode* node = 0;
2319  node = sceneGraphRoot_->find("Core Coordsys Node");
2320  if(node != 0 && formerCoordsysState) {
2321  node->show();
2322  }
2323  }
2324 
2325 
2326  }
2327 
2328  if(_width != 0 || _height != 0) {
2329  // Reset viewport to former size
2330  glstate_->viewport(left, bottom, bak_w, bak_h);
2331  }
2332 
2335 }
2336 
2337 
2338 void glViewer::snapshot( int _width, int _height, bool _alpha, bool _hideCoordsys, int samples)
2339 {
2340  QImage image;
2341 
2342  // Capture image
2343  snapshot(image, _width, _height, _alpha, _hideCoordsys, samples);
2344 
2345  /*
2346  * Meta data
2347  */
2348  QString comments = PluginFunctions::collectObjectComments(true, false).join("\n");
2349  if (!comments.isEmpty())
2350  image.setText("Mesh Comments", comments);
2351  QString view;
2352  encodeView(view);
2353  image.setText("View", view);
2354 
2355  QFileInfo fi(properties_.snapshotName());
2356 
2357  QString fname = fi.path() + QDir::separator() +fi.baseName() + "." + QString::number(properties_.snapshotCounter()).rightJustified(7,'0') + "." + properties_.snapshotFileType().toLower();
2358 
2359  QImageWriter writer(fname);
2360  writer.setFormat(properties_.snapshotFileType().simplified().toLatin1());
2361 
2362  bool rval = writer.canWrite();
2363  if (rval)
2364  writer.write(image);
2365 
2366  if (rval)
2367  emit statusMessage (QString(tr("Snapshot: "))+fname,5000);
2368  else
2369  emit statusMessage (QString(tr("Could not save snapshot to ")) + fname + QString(tr(" Error: ")) + writer.errorString() );
2370 }
2371 
2372 void glViewer::slotHideWheels() {
2373  if (isVisible())
2374  {
2375  wheelX_->hide();
2376  wheelY_->hide();
2377  wheelZ_->hide();
2378  }
2379  else
2380  {
2381  show ();
2382  wheelX_->hide();
2383  wheelY_->hide();
2384  wheelZ_->hide();
2385  hide ();
2386  }
2387 }
2388 
2389 void glViewer::slotShowWheels() {
2390  if (isVisible())
2391  {
2392  wheelX_->show();
2393  wheelY_->show();
2394  wheelZ_->show();
2395  }
2396  else
2397  {
2398  show ();
2399  wheelX_->show();
2400  wheelY_->show();
2401  wheelZ_->show();
2402  hide ();
2403  }
2404 }
2405 
2406 bool glViewer::wheelsVisible() {
2407  // TODO: Return valid values
2408  return true;
2409 }
2410 
2411 //-----------------------------------------------------------------------------
2412 
2414 {
2415  emit signalMouseEventClick (&clickEvent_, false);
2416 }
2417 
2418 //-----------------------------------------------------------------------------
2419 
2421 {
2422  properties_.cursorPainter( _cursorPainter );
2423 }
2424 
2425 //-----------------------------------------------------------------------------
2426 
2427 void glViewer::updateCursorPosition (QPointF _scenePos)
2428 {
2429  if (!initialized_ || !sceneGraphRoot_ || !isVisible ())
2430  return;
2431 
2432  ACG::Vec3d tmp;
2433 
2434  unsigned int nodeIdx = 0;
2435  unsigned int targetIdx = 0;
2436 
2437 
2438  // ignore cursor if we are outside of our window
2439  if (!mapRectToScene(boundingRect ()).intersects (properties_.cursorPainter()->cursorBoundingBox().translated(_scenePos)))
2440  {
2442  }
2443  // only do real pick in stereo mode
2444  else if ( properties_.stereo() && OpenFlipperSettings().value("Core/Gui/glViewer/stereoMousePick",true).toBool() &&
2445  pick (ACG::SceneGraph::PICK_ANYTHING, _scenePos.toPoint(), nodeIdx, targetIdx, &tmp))
2446  {
2447  // the point we get back will contain the view transformation and we have to revert it
2450  }
2451  // only do real pick in stereo mode
2452  else
2453  {
2455 
2456  // reset modelview to ignore the view transformation
2458 
2459  // Project the depth value of the stereo mode zero paralax plane.
2460  // We need to use this depth to to get the cursor exactly on zero paralax plane in stereo mode
2461  double zerop = properties_.nearPlane() + ((properties_.farPlane() - properties_.nearPlane()) * OpenFlipperSettings().value("Core/Stereo/FocalLength").toDouble() );
2462  ACG::Vec3d zerod = glstate_->project (ACG::Vec3d (0.0, 0.0, -zerop));
2463 
2464  // unproject the cursor into the scene
2465  properties_.cursorPoint3D( glstate_->unproject (ACG::Vec3d (_scenePos.x(), scene()->height () - _scenePos.y(), zerod[2])) );
2466 
2468 
2470  }
2471 }
2472 
2473 //-----------------------------------------------------------------------------
2474 
2475 
2477  if(navigationMode_ == FIRSTPERSON_NAVIGATION) {
2478 
2480 
2481  dir *= -0.1;
2482 
2483  glstate_->translate(dir[0], dir[1], dir[2]);
2484 
2485  updateGL();
2486  lastMoveTime_.restart();
2487 
2488  emit viewChanged();
2489  }
2490 }
2491 
2493  if(navigationMode_ == FIRSTPERSON_NAVIGATION) {
2495 
2496  dir *= 0.1;
2497 
2498  glstate_->translate(dir[0], dir[1], dir[2]);
2499 
2500  updateGL();
2501  lastMoveTime_.restart();
2502 
2503  emit viewChanged();
2504  }
2505 }
2506 
2508  if(navigationMode_ == FIRSTPERSON_NAVIGATION) {
2509  ACG::Vec3d dir = glstate_->right();
2510 
2511  dir *= 0.1;
2512 
2513  glstate_->translate(dir[0], dir[1], dir[2]);
2514 
2515  updateGL();
2516  lastMoveTime_.restart();
2517 
2518  emit viewChanged();
2519  }
2520 }
2521 
2523  if(navigationMode_ == FIRSTPERSON_NAVIGATION) {
2524  ACG::Vec3d dir = glstate_->right();
2525 
2526  dir *= -0.1;
2527 
2528  glstate_->translate(dir[0], dir[1], dir[2]);
2529 
2530  updateGL();
2531  lastMoveTime_.restart();
2532 
2533  emit viewChanged();
2534  }
2535 }
2536 
2537 
2538 
2539 void glViewer::computeProjStereo( int _viewportWidth, int _viewportHeight, Viewer::ViewerProperties& _properties, ACG::GLMatrixd* _outLeft, ACG::GLMatrixd* _outRight )
2540 {
2541  double l, r, t, b, w, h, a, radians, wd2, ndfl, zerop, xrange;
2542 
2543  w = double(_viewportWidth);
2544  h = double(_viewportHeight);
2545  a = w / h;
2546 
2547  double fovy = OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble();
2548  radians = fovy * 0.5 / 180.0 * M_PI;
2549  wd2 = _properties.nearPlane() * tan(radians);
2550  zerop = _properties.nearPlane() + ((_properties.farPlane() - _properties.nearPlane()) * OpenFlipperSettings().value("Core/Stereo/FocalDistance", 0.5).toDouble() );
2551  ndfl = _properties.nearPlane() / zerop ;
2552  xrange = a * wd2 * 2 * zerop / _properties.nearPlane();
2553 
2554  l = -a*wd2;
2555  r = a*wd2;
2556  t = wd2;
2557  b = -wd2;
2558 
2559  double offset = 0.5 * OpenFlipperSettings().value("Core/Stereo/EyeDistance", 0.07).toDouble() * xrange;
2560  double offset2 = offset * ndfl;
2561 
2562  if (_outLeft)
2563  {
2564  _outLeft->identity();
2565  _outLeft->frustum(l+offset2, r+offset2, b, t, _properties.nearPlane(), _properties.farPlane());
2566  _outLeft->translate(offset, 0.0, 0.0);
2567  }
2568 
2569  if (_outRight)
2570  {
2571  _outRight->identity();
2572  _outRight->frustum(l-offset2, r-offset2, b, t, _properties.nearPlane(), _properties.farPlane());
2573  _outRight->translate(-offset, 0.0, 0.0);
2574  }
2575 }
2576 
2577 
2578 //=============================================================================
2579 //=============================================================================
2580 
ACG::Vec3d unproject(const ACG::Vec3d &pt)
Framebuffer object that holds the pick cache.
double wheelZoomFactorShift()
Zoom factor when using mouse wheel and pressing shift.
void encodeView(QString &_view, const QSize &_windowSize=QSize(-1,-1), const int _toolBarWidth=-1, const bool _make_c_string=false)
static void enable(GLenum _cap)
replaces glEnable, but supports locking
Definition: GLState.cc:1490
unsigned int activeId(int _id)
Get the id of the active renderer.
void sceneGraph(ACG::SceneGraph::BaseNode *_root, unsigned int _maxPasses, ACG::Vec3d _bbmin, ACG::Vec3d _bbmax, const bool _resetTrackBall=false)
bool wheelInvert()
Invert mouse wheel direction?
virtual bool blendForStencilRefBit(GLuint _refbit, GLenum &_src, GLenum &_dst, ACG::Vec4f &_color)
void push_projection_matrix()
push projection matrix
Definition: GLState.cc:967
void slotPropertiesUpdated()
void clearBuffers()
clear buffers viewport rectangle
Definition: GLState.cc:266
Vec3d eye() const
get eye point
Definition: GLState.cc:882
virtual void home()
go to home pos
virtual ~glViewer()
Destructor.
virtual void paintGL(double _aspect=0.0)
draw the scene. Triggered by updateGL().
void setState()
set the whole stored gl state
Definition: GLState.cc:209
RendererInfo * active(int _id)
Get the current active renderer.
void pop_projection_matrix()
pop projection matrix
Definition: GLState.cc:985
QMouseEvent clickEvent_
mouse interaction position
virtual void setFOVY(double _fovy)
Set fovy.
VectorT< T, 3 > transform_point(const VectorT< T, 3 > &_v) const
transform point (x&#39;,y&#39;,z&#39;,1) = M * (x,y,z,1)
Definition: Matrix4x4T.cc:202
bool enabled()
Returns true if cursor painting is enabled and compatible cursor is set.
void animation(bool _state)
set 2-sided lighting on/off
void setProjectionMode(const ProjectionMode _mode)
set mode to either ORTHOGRAPHIC_PROJECTION or PERSPECTIVE_PROJECTION
static void unlockBlendFuncSeparate()
unlock blend func
Definition: GLState.hh:337
virtual void resizeEvent(QGraphicsSceneResizeEvent *_e)
handle resize events
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
Definition: GLMatrixT.cc:102
void stereo(bool _stereo)
Flag if stereo should be enabled for the current viewer.
void set_twosided_lighting(bool _b)
set whether transparent or solid objects should be drawn
Definition: GLState.cc:818
void lookAt(const Vec3d &_eye, const Vec3d &_center, const Vec3d &_up)
set camera by lookAt
Definition: GLState.cc:513
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:144
void slotAnimation()
mouse interaction position
ACG::GLState * glstate_
Gl State.
void startDragEvent(QMouseEvent *_event)
bool pick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, unsigned int &_nodeIdx, unsigned int &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
virtual bool stencilRefForObject(BaseObjectData *_obj, GLuint &_reference)=0
bool updatePickCache_
Should the pick cache be updated.
ProjectionMode
projection mode
unsigned int glWidth() const
get width of QGLWidget
void slotClickTimeout()
Handle click timeout.
QTimer * timer_
mouse interaction position
void strafeLeft()
First person navigation: Strafe left.
virtual void wheelEvent(QGraphicsSceneWheelEvent *_event)
handle mouse wheel events
void signalMouseEventClick(QMouseEvent *, bool _double)
void initModelviewMatrix()
initialize modelview matrix to identity
void lookAt(const ACG::Vec3d &_eye, const ACG::Vec3d &_center, const ACG::Vec3d &_up)
Set look at transformation directly.
void push_modelview_matrix()
push modelview matrix
Definition: GLState.cc:1006
void traverse_multipass(BaseNode *_node, Action &_action, const unsigned int &_pass)
Definition: SceneGraph.hh:260
QTime lastMoveTime_
mouse interaction position
ACG::Vec3d lastRotationAxis_
mouse interaction position
bool backFaceCulling()
Get current state of backface culling.
QTimer clickTimer_
mouse interaction position
void moveBack()
First person navigation: Move back.
void perspective(double _fovY, double _aspect, double _near_plane, double _far_plane)
perspective projection
Definition: GLState.cc:446
void viewingDirection(const ACG::Vec3d &_dir, const ACG::Vec3d &_up)
set the viewing direction
void set_bounding_box(ACG::Vec3d _min, ACG::Vec3d _max)
Definition: GLState.cc:802
ACG::Vec3d cursorPoint3D()
Flag if stereo should be enabled for the current viewer.
void setPlanes(double _near, double _far)
Set near and far plane at the same time.
void unLockUpdate()
Unlock display locked by updateLock().
virtual void dropEvent(QGraphicsSceneDragDropEvent *_e)
drag & drop for modelview copying
QPoint glMapToGlobal(const QPoint &_pos) const
map glarea coords to global coords
void signalWheelEvent(QWheelEvent *, const std::string &)
Emitted in Pick mode. Uses pick mode.
void objectMarker(ViewObjectMarker *_marker)
set object marker for viewer
int numActive(int _id)
Get the number of active post processors for viewer.
virtual void perspectiveProjection()
set perspective view (projectionMode(PERSPECTIVE_PROJECTION))
virtual void slotWheelY(double _dAngle)
process signals from wheelX_
double sceneRadius()
Get radius of the current scene.
virtual void setView(const ACG::GLMatrixd &_modelview, const ACG::GLMatrixd &_inverse_modelview)
set view, used for synchronizing
void snapshotCounter(const int _counter)
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
void signalMouseEvent(QMouseEvent *, const std::string &)
double farPlane()
Return distance to far Plane.
ChildIter find(BaseNode *_node)
Definition: BaseNode.hh:377
void handleNormalNavigation(QMouseEvent *_event)
Navigate through scene if normal mode has been selected.
virtual void toggleProjectionMode()
toggle projection mode
void signalMouseEventLight(QMouseEvent *)
QGLFramebufferObjectFormat QFramebufferObjectFormat
Framebuffer object that holds the pick cache.
void copyToImage(QImage &_image, GLenum _buffer=GL_BACK)
copy current framebuffer to an QImage
Viewer::ActionMode actionMode()
get the action mode
int viewport_width() const
get viewport width
Definition: GLState.hh:825
static GLuint getFramebufferDraw()
get current draw framebuffer of a target
Definition: GLState.cc:1994
void allow_multisampling(bool _b)
Disable multisampling globally.
Definition: GLState.hh:1054
virtual void mousePressEvent(QGraphicsSceneMouseEvent *_event)
handle mouse press events
const QStringList ALL_OBJECTS
Iterable object range.
static void bindFramebuffer(GLenum _target, GLuint _framebuffer)
replaces glBindFramebuffer, supports locking
Definition: GLState.cc:2009
void applyProperties()
QRectF cursorBoundingBox()
Bounding box of the cursor.
void ortho(double _left, double _right, double _bottom, double _top, double _near_plane, double _far_plane)
orthographic projection
Definition: GLState.cc:400
static void bindBuffer(GLenum _target, GLuint _buffer)
replaces glBindBuffer, supports locking
Definition: GLState.cc:1764
PostProcessing * postproc_
Post-Processing executor.
virtual void flyTo(const QPoint &_pos, bool _moveBack)
Animated flight to or away from a given point.
void computeProjStereo(int _width, int _height, Viewer::ViewerProperties &_properties, ACG::GLMatrixd *_outLeft, ACG::GLMatrixd *_outRight)
Compute left and right eye projection matrix for stereo rendering.
void viewport(int _left, int _bottom, int _width, int _height, int _glwidth=0, int _glheight=0)
set viewport (lower left corner, width, height, glcontext width, height)
Definition: GLState.cc:468
void handleFirstPersonNavigation(QMouseEvent *_event)
Navigate through scene if first person mode has been selected.
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition: GLState.cc:638
NormalsMode
Automatically normalize normals?
ProjectionMode projectionMode() const
get current projection mode
void drawCursor()
draw the cursor
Vec3d up() const
get up-vector w.r.t. camera coordinates
Definition: GLState.cc:902
static void lockBlendFuncSeparate(bool _rgb=true, bool _alpha=true)
lock blend func
Definition: GLState.hh:335
void paintCursor(ACG::GLState *_state)
Cursor painting function. The _state has to be setup that 0,0,0 is at the cursor position.
virtual void orthographicProjection()
set orthographic view (projectionMode(ORTHOGRAPHIC_PROJECTION))
const GLMatrixd & inverse_modelview() const
get inverse modelview matrix
Definition: GLState.hh:814
QSize glSize() const
get size of QGLWIdget
void viewWheelEvent(QWheelEvent *_event)
specialized viewer: handle wheel events
void identity()
setup an identity matrix
Definition: Matrix4x4T.cc:256
void trackMouse(bool _track)
Enable/disable mouse tracking (move events with no button press)
void setCoordSysProjection(glViewer::ProjectionMode _mode)
helper function for setting the projection mode of the coordinate system node
Interface to add additional rendering functions from within plugins.
NormalsMode normalsMode() const
get treatment of normals
glViewer(QGraphicsScene *_scene, QGLWidget *_glWidget, Viewer::ViewerProperties &_properties, QGraphicsWidget *_parent=0)
static double deg(double _angle)
maps _angle from radiants to degrees (works also for clip()ped angles)
Definition: QtWheel.cc:447
ACG::Vec3d lastPoint3D_
mouse interaction position
void postProcess(int _viewerID, ACG::GLState *_glstate, const ACG::GLMatrixd &_modelview, const ACG::GLMatrixd &_proj1, const ACG::GLMatrixd &_proj2, bool _hwOpenGLStereo=false)
Perform all post processing.
Viewer::ViewerProperties & properties_
All properties for this viewer.
void actionCopyView(const QSize &_windowSize=QSize(-1,-1), const int _splitterWidth=-1, const bool _make_c_string=false)
bool initialized_
Have the viewer gl properties been initalized.
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
double far_plane() const
Returns a peanut butter sandwich.
void translate(double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
translate by (_x, _y, _z)
Definition: GLState.cc:531
void multisampling(bool _state)
set multisampling on/off
double orthoWidth()
Get width of the gl scene in orthogonal projection mode (defaults to 2.0)
unsigned int glHeight() const
get height of QGLWidget
void set_msSinceLastRedraw(unsigned int _ms)
set time passed since last redraw in milliseconds
Definition: GLState.hh:248
const DataType DATA_ALL(UINT_MAX)
Identifier for all available objects.
void hide()
Hide Node: set status to HideNode.
Definition: BaseNode.hh:436
virtual void slotWheelZ(double _dist)
process signals from wheelZ_
CursorPainter * cursorPainter()
Flag if stereo should be enabled for the current viewer.
void analyzeSceneGraph(ACG::SceneGraph::BaseNode *_root, unsigned int &_maxPasses, ACG::Vec3d &_bbmin, ACG::Vec3d &_bbmax)
Analyze the SceneGraph <ACG/Scenegraph/SceneGraphAnalysis.hh>
double fovyModifier_
mouse interaction position
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Vec3d unproject(const Vec3d &_winPoint) const
unproject point in window coordinates _winPoint to world coordinates
Definition: GLState.cc:649
void updateProjectionMatrix(double _aspect=0.0)
updates projection matrix
void set_modelview(const GLMatrixd &_m)
set modelview
Definition: GLState.hh:731
void resolveStereoAnyglyph(int _viewerID)
Resolve stereo buffers as anaglyph.
double aspect_ratio() const
Returns the viewer&#39;s aspect ratio.
void grabGLArea()
get all Mouse & Key Events for GlWidget
void setScenePos(const ACG::Vec3d &_center, double _radius, const bool _resetTrackBall=false)
virtual void makeCurrent()
Makes this widget the current widget for OpenGL operations.
void viewUpdated()
This signal is emitted when the scene is repainted due to any event.
ACG::Vec3d trackballCenter()
Get virtual trackball center (rotation center when using mouse)
void signalSceneGraphChanged(ACG::SceneGraph::BaseNode *_root)
scene graph has changed
static double clip(double _angle)
Definition: QtWheel.cc:443
virtual void swapBuffers()
Swaps the screen contents with the off-screen buffer.
void signalCustomContextMenuRequested(const QPoint &)
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *_event)
handle mouse move events
virtual void moveEvent(QGraphicsSceneMoveEvent *_e)
handle move events
void moveForward()
First person navigation: Move forward.
Viewer::ViewerProperties * properties()
Returns a pointer to the Viewer Status.
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *_event)
handle mouse release events
QPoint lastPoint2D_
mouse interaction position
bool lastPoint_hitSphere_
mouse interaction position
void twoSidedLighting(bool _state)
set 2-sided lighting on/off
double trackballRadius()
Get trackball radius (rotation sphere when using mouse)
virtual void setHome()
set home position
static bool decodeView(const QString &_view, ACG::GLMatrixd &m, ACG::GLMatrixd &p, int &pMode, double &ortho_width, QSize *_windowSize=NULL, int *_splitterWidth=NULL, QSize *_viewportSize=NULL)
double lastRotationAngle_
mouse interaction position
NavigationMode
Navigation mode.
void strafeRight()
First person navigation: Strafe Right.
std::string pickMode()
get active pick mode
void setViewerID(int _viewerID)
Set currently active viewer id.
Definition: IRenderer.cc:1412
virtual void render(ACG::GLState *_glState, Viewer::ViewerProperties &_properties)
rendering function
use provided normals as is
void viewMouseEvent(QMouseEvent *_event)
specialized viewer: hande mouse events
static void activeTexture(GLenum _texunit)
replaces glActiveTexture, no locking support
Definition: GLState.cc:1801
void translate(const ACG::Vec3d &trans)
translate the scene and update modelview matrix
void pop_modelview_matrix()
pop modelview matrix
Definition: GLState.cc:1022
void set_projection(const GLMatrixd &_m)
set projection
Definition: GLState.hh:694
void signalMakeActive()
make this widget active
int viewerId()
Get the id of the viewer this viewerproperties belongs to.
void rotate(double _angle, double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
rotate around axis (_x, _y, _z) by _angle
Definition: GLState.cc:562
double ortho_width() const
Get width of the gl scene in orthogonal projection mode.
static void disable(GLenum _cap)
replaces glDisable, but supports locking
Definition: GLState.cc:1504
void frustum(Scalar left, Scalar right, Scalar bottom, Scalar top, Scalar near_plane, Scalar far_plane)
multiply self with a perspective projection matrix
Definition: GLMatrixT.cc:317
virtual void viewAll()
view the whole scene
void reset_projection()
reset projection matrix (load identity)
Definition: GLState.cc:332
bool allowRotation_
mouse interaction position
void show()
Show node: set status to Active.
Definition: BaseNode.hh:438
void actionPasteView(QSize *_windowSize=NULL, int *_splitterWidth=NULL)
bool mapToSphere(const QPoint &_p, ACG::Vec3d &_result) const
virtual trackball: map 2D screen point to unit sphere
void snapshotFileType(const QString &_type)
virtual void slotWheelX(double _dAngle)
process signals from wheelX_
bool cursorPositionValid()
Flag if stereo should be enabled for the current viewer.
bool fast_pick(const QPoint &_mousePos, ACG::Vec3d &_hitPoint)
void set_clear_color(const Vec4f &_col)
set background color
Definition: GLState.cc:660
void addWheelX(QGraphicsWidget *_item)
Add Wheel Widget to Layout.
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *_event)
handle mouse double click events
ACG::Vec3d constrainedRotationAxis_
mouse interaction position
const GLMatrixd & projection() const
get projection matrix
Definition: GLState.hh:789
bool allowConstrainedRotation()
mouse interaction position
void signalMouseEventIdentify(QMouseEvent *)
QTime clickTime_
mouse interaction position
void drawMode(ACG::SceneGraph::DrawModes::DrawMode _mode)
set draw mode (No test if this mode is available!)
QGLFramebufferObject QFramebufferObject
Framebuffer object that holds the pick cache.
double wheelZoomFactor()
Zoom factor when using mouse wheel.
STL namespace.
virtual void dragEnterEvent(QGraphicsSceneDragDropEvent *_e)
drag & drop for modelview copying
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:794
void viewChanged()
This signal is emitted whenever the view is changed by the user.
virtual QSize sizeHint() const
reimplemented
Definition: QtWheel.cc:432
float startDepth_
mouse interaction depth
Mark per returned reference bits.
static void bindTexture(GLenum _target, GLuint _buffer)
replaces glBindTexture, supports locking
Definition: GLState.cc:1812
void setCursor(const QCursor &_cursor)
Sets the current used cursor.
bool visible()
Is node visible (status == Active)?
Definition: BaseNode.hh:440
pick any of the prior targets (should be implemented for all nodes)
Definition: BaseNode.hh:110
double near_plane() const
Returns a chili cheese burger.
int viewport_height() const
get viewport height
Definition: GLState.hh:827
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
void set_max_render_passes(const unsigned int _max)
set maximum number of render passes
Definition: GLState.hh:999
virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *_e)
handle mouse press events
virtual void updateGL()
Redraw scene. Triggers paint event for updating the view (cf. drawNow()).
void get_viewport(int &_left, int &_bottom, int &_width, int &_height) const
get viewport
Definition: GLState.hh:819
virtual bool blendForStencilRefNumber(GLuint _reference, GLenum &_src, GLenum &_dst, ACG::Vec4f &_color)
virtual void toggleNavigationMode()
toggle navigation mode
void setglState(ACG::GLState *_glState)
Pointer to the glState of the Viewer.
Vec3d right() const
get right-vector w.r.t. camera coordinates
Definition: GLState.cc:914
void initialize()
initialize all state variables (called by constructor)
Definition: GLState.cc:162
static void drawBuffer(GLenum _mode)
replaces glDrawBuffer, supports locking
Definition: GLState.cc:1953
int setupScene(int _viewerID, int _width, int _height, int _samples=0, int _stereoEye=-1)
Bind fbo for scene rendering.
QStringList collectObjectComments(bool visibleOnly, bool targetedOnly)
NavigationMode navigationMode() const
get current navigation mode
ACG::Vec3d sceneCenter()
Get current scene center (rendering center)
virtual void initializeGL()
Return a resonable size hint.
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:127
static void blendFuncSeparate(GLenum _srcRGB, GLenum _dstRGB, GLenum _srcAlpha, GLenum _dstAlpha)
replaces glBlendFuncSeparate, supports locking
Definition: GLState.cc:1592
ACG::Vec4f backgroundColor()
Get current background color.
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
QPoint glMapFromGlobal(const QPoint &_pos) const
map global to glarea coords
void reset_modelview()
reset modelview matrix (load identity)
Definition: GLState.cc:368
VectorT< T, 3 > transform_vector(const VectorT< T, 3 > &_v) const
transform vector (x&#39;,y&#39;,z&#39;,0) = A * (x,y,z,0)
Definition: Matrix4x4T.cc:225
void setCursorPainter(CursorPainter *_cursorPainter)
sets the current cursor painter
void rotate(const ACG::Vec3d &axis, double angle)
rotate the scene (around its center) and update modelview matrix
void releaseGLArea()
undo grabbing GLArea
virtual void snapshot(int _width=0, int _height=0, bool _alpha=false, bool _hideCoordsys=false, int samples=1)
double nearPlane()
Return distance to near Plane.
void updateCursorPosition(QPointF _scenePos)
will be called from CursorPainter to inform the viewer that the cursor position changed ...
Vec3d viewing_direction() const
get viewing ray
Definition: GLState.hh:851
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
Definition: GLState.hh:314
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
Definition: GLState.cc:1700