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