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_(0),
130  pickCache_(0),
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_(0),
140  flyAnimationOrthogonal_(0),
141  flyAngle_(0.0),
142  currentAnimationPos_(0.0),
143  flyMoveBack_(false),
144  postproc_(0)
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_ = 0;
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 = 0;
315  node = PluginFunctions::getSceneGraphRootNode()->find("Core Coordsys Node");
316 
317  // set the projection mode for the coordinate system node
318  if (node != 0) {
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  QTime 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 backbufferFbo = 0;
666  GLuint backbufferTarget = 0;
667  glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&backbufferFbo);
668  glGetIntegerv(GL_DRAW_BUFFER, (GLint*)&backbufferTarget);
669 
670  // setup stereo rendering
671 
672  // left eye: fbo 0
673  // right eye: fbo 1
674 
675  for (int eye = 0; eye < 2; ++eye) {
676  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, backbufferFbo);
698  glDrawBuffer(backbufferTarget);
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  o_it != PluginFunctions::objectsEnd(); ++o_it)
766  {
767  bool ok;
768  GLuint ref;
769 
770  ok = oM->stencilRefForObject(*o_it, ref);
771 
772  if (ok)
773  {
774  o_it->stencilRefNode ()->setReference (ref);
775  o_it->stencilRefNode ()->show ();
776  refBits |= ref;
777  references << ref;
778  }
779  else
780  o_it->stencilRefNode ()->hide ();
781  }
782  }
783 
784  // First pass
787 
788  // Second Pass for Blending operations
791 
792  if (oM)
793  {
794  if (oM->type() == ViewObjectMarker::PerBit)
795  {
796  references.clear ();
797  for (unsigned int i = 0; i < sizeof (GLuint) * 8; i++)
798  if (refBits & (1 << i))
799  references << (1 << i);
800  }
801 
802  glPushAttrib(GL_ALL_ATTRIB_BITS);
803 
804  ACG::GLState::enable(GL_BLEND);
805  ACG::GLState::disable(GL_DEPTH_TEST);
806 
807  if (glstate_->compatibilityProfile())
808  ACG::GLState::disable(GL_LIGHTING);
809 
810  ACG::GLState::disable(GL_DITHER);
811 
812  int vp_l, vp_b, vp_w, vp_h;
813  glstate_->get_viewport (vp_l, vp_b, vp_w, vp_h);
814 
815  glMatrixMode(GL_PROJECTION);
816  glPushMatrix ();
817  glLoadIdentity();
818  glOrtho(0, vp_w, vp_h, 0, 0, 1.0);
819  glMatrixMode(GL_MODELVIEW);
820  glPushMatrix ();
821  glLoadIdentity();
822 
823  glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
824 
825  foreach (unsigned int ref, references)
826  {
827  bool ok;
828  GLenum sfactor;
829  GLenum dfactor;
830  ACG::Vec4f color;
831  unsigned int mask = ~0;
832 
833  if (oM->type() == ViewObjectMarker::PerBit)
834  {
835  ok = oM->blendForStencilRefBit (ref, sfactor, dfactor, color);
836  mask = ref;
837  }
838  else
839  ok = oM->blendForStencilRefNumber (ref, sfactor, dfactor, color);
840 
841  if (!ok)
842  continue;
843 
844  glStencilFunc (GL_EQUAL, ref, mask);
845 
846  ACG::GLState::blendFunc (sfactor, dfactor);
847  glColor4f (color[0], color [1], color [2], color[3]);
848 
849  glBegin (GL_QUADS);
850  glVertex2i(0, 0);
851  glVertex2i(0, vp_h);
852  glVertex2i(vp_w, vp_h);
853  glVertex2i(vp_w, 0);
854  glEnd ();
855 
856  }
857 
858  glMatrixMode(GL_PROJECTION);
859  glPopMatrix ();
860  glMatrixMode(GL_MODELVIEW);
861  glPopMatrix ();
862 
863  glPopAttrib ();
864  ACG::GLState::disable (GL_STENCIL_TEST);
865  }
866 
867 
868  }
869 
870  drawCursor();
871 
872 }
873 
874 
876 {
878  {
880  // reset view transformation
882  // translate cursor position to 0,0
884  // paint cursor
887  }
888 }
889 
890 
892 {
893  home_modelview_ = glstate_->modelview();
894  home_inverse_modelview_ = glstate_->inverse_modelview();
895  homeOrthoWidth_ = properties_.orthoWidth();
896  home_center_ = properties_.trackballCenter();
897  home_radius_ = properties_.trackballRadius();
898 }
899 
900 
902 {
903  makeCurrent();
904  glstate_->set_modelview(home_modelview_, home_inverse_modelview_);
905  properties_.orthoWidth( homeOrthoWidth_ );
906  properties_.trackballCenter( home_center_ );
907  properties_.trackballRadius(home_radius_);
909  updateGL();
910 
911  emit viewChanged();
912 
913 }
914 
915 //-----------------------------------------------------------------------------
916 
918 {
919  makeCurrent();
920  // update scene graph (get new bounding box and set projection right, including near and far plane)
922 
923  unsigned int maxPases = 1;
924  ACG::Vec3d bbmin,bbmax;
925  // update scene bounding boxes
927 
928  // update scene properties (near, far plane, scene radius according to the computed bounding boxes)
929  sceneGraph ( PluginFunctions::getSceneGraphRootNode(), maxPases,bbmin,bbmax,true);
930 
931 
932  // update camera
933  // move center (in camera coords) to origin and translate in -z dir
935  - ACG::Vec3d(0.0, 0.0, 3.0 * properties_.sceneRadius()));
936 
938  double aspect = (double) glWidth() / (double) glHeight();
939  if (aspect > 1.0)
941 
944  updateGL();
945 
946  emit viewChanged();
947 
948 }
949 
950 
951 //-----------------------------------------------------------------------------
952 
953 
954 void glViewer::setView(const ACG::GLMatrixd& _modelview,
955  const ACG::GLMatrixd& _inverse_modelview)
956 {
957  makeCurrent();
958  glstate_->set_modelview(_modelview, _inverse_modelview);
959  updateGL();
960 
961  emit viewChanged();
962 }
963 
964 
965 //-----------------------------------------------------------------------------
966 
967 
969 {
970 
971  // lock update
973 
974  // init GL state
975  glstate_->initialize();
976 
977  // OpenGL state
978  ACG::GLState::enable(GL_DEPTH_TEST);
979 
980  if (glstate_->compatibilityProfile())
981  {
982  ACG::GLState::enable(GL_LIGHTING);
983  ACG::GLState::shadeModel(GL_FLAT);
984  }
985 
986  ACG::GLState::disable(GL_DITHER);
987 
988 
989  projectionMode( projectionMode_ );
990  normalsMode( normalsMode_ );
991 
992  // Update all settings which would require a redraw
993  applyProperties();
994 
995  // modelview
996  glstate_->translate(0.0, 0.0, -3.0);
997  setHome();
998 
999  // pixel transfer
1000  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1001  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
1002  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
1003  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1004  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
1005  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1006  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1007  glPixelStorei(GL_PACK_ALIGNMENT, 1);
1008 
1009 
1010  // unlock update (we started locked)
1012 
1013  initialized_ = true;
1014 
1015  if (sceneGraphRoot_)
1016  {
1017  unsigned int maxPases = 1;
1018  ACG::Vec3d bbmin,bbmax;
1019  ACG::SceneGraph::analyzeSceneGraph(sceneGraphRoot_,maxPases,bbmin,bbmax);
1020 
1021  sceneGraph ( sceneGraphRoot_, maxPases,bbmin,bbmax,true);
1022  viewAll();
1023  }
1024 
1025 
1026  // qt opengl info
1027  startGLDebugLogger();
1028 }
1029 
1030 
1031 //-----------------------------------------------------------------------------
1032 
1033 
1034 void glViewer::paintGL(double _aspect)
1035 {
1036  if (!initialized_)
1037  initializeGL ();
1038 
1039 
1040  // some drivers in core profile require a VAO object to be bound for all buffer array operations
1041  if (!glstate_->compatibilityProfile())
1042  {
1043  if (!defaultVAO_.isSupported())
1044  std::cerr << "Error - using core profile, but required VAO is not supported!" << std::endl;
1045  else
1046  defaultVAO_.bind();
1047  }
1048 
1049 
1050  if (!properties_.updateLocked())
1051  {
1053 
1054  GLboolean dtenabled;
1055  glGetBooleanv(GL_DEPTH_TEST, &dtenabled);
1056  ACG::GLState::enable(GL_DEPTH_TEST);
1057 
1058  if (glstate_->compatibilityProfile())
1059  {
1060  glPushAttrib(GL_ALL_ATTRIB_BITS);
1061  ACG::GLState::enable(GL_LIGHTING);
1062 
1063  glMatrixMode(GL_PROJECTION);
1064  glPushMatrix();
1065 
1066  glMatrixMode(GL_MODELVIEW);
1067  glPushMatrix();
1068 
1069 
1070  normalsMode(normalsMode_);
1071 
1072  ACG::GLState::shadeModel(GL_FLAT);
1073  }
1074 
1075  ACG::GLState::disable(GL_DITHER);
1076 
1077 
1078  applyProperties();
1079 
1080  glstate_->setState();
1081 
1082  if (glstate_->compatibilityProfile())
1083  glColor4f(1.0,0.0,0.0,1.0);
1084 
1085  glstate_->clearBuffers ();
1086 
1088 
1089  // draw scene
1090  drawScene(_aspect);
1091 
1092  if (glstate_->compatibilityProfile())
1093  {
1094  glPopMatrix();
1095 
1096  glMatrixMode(GL_PROJECTION);
1097  glPopMatrix();
1098 
1099  glPopAttrib();
1100  }
1101  if(dtenabled)
1102  ACG::GLState::enable(GL_DEPTH_TEST);
1103  else
1104  ACG::GLState::disable(GL_DEPTH_TEST);
1105  }
1106  glBindBuffer(GL_ARRAY_BUFFER, 0);
1107  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1108 }
1109 
1110 
1111 //-----------------------------------------------------------------------------
1112 
1113 
1114 void glViewer::resizeEvent(QGraphicsSceneResizeEvent *)
1115 {
1117  glstate_->viewport(scenePos().x(),
1118  scene()->height () - scenePos().y() - size().height (),
1119  size().width (), size().height (),
1120  scene()->width (), scene()->height ());
1121  update();
1122 
1123  emit viewChanged();
1124 }
1125 
1126 void glViewer::moveEvent (QGraphicsSceneMoveEvent *)
1127 {
1128  glstate_->viewport(scenePos().x(),
1129  scene()->height () - scenePos().y() - size().height (),
1130  size().width (), size().height (),
1131  scene()->width (), scene()->height ());
1132  update();
1133 
1134  emit viewChanged();
1135 }
1136 
1137 //-----------------------------------------------------------------------------
1138 
1139 void glViewer::encodeView(QString& _view, const QSize& _windowSize /*= QSize()*/,
1140  const int _splitterWidth /*=-1*/, const bool _make_c_string /*= false*/)
1141 {
1142  // Get current matrices
1143  const ACG::GLMatrixd m = glstate_->modelview();
1144  const ACG::GLMatrixd p = glstate_->projection();
1145 
1146  static const char *line_delim_c = " \\\n";
1147  static const char *line_delim_std = line_delim_c + 2;
1148  const char *line_delim = _make_c_string ? line_delim_c : line_delim_std;
1149 
1150  if (_make_c_string)
1151  _view += "\"";
1152 
1153  // Add modelview matrix to output
1154  _view += QString(COPY_PASTE_VIEW_START_STRING) + line_delim;
1155  _view += QString::number(m(0,0)) + " " + QString::number(m(0,1)) + " " + QString::number(m(0,2)) + " " + QString::number(m(0,3)) + line_delim;
1156  _view += QString::number(m(1,0)) + " " + QString::number(m(1,1)) + " " + QString::number(m(1,2)) + " " + QString::number(m(1,3)) + line_delim;
1157  _view += QString::number(m(2,0)) + " " + QString::number(m(2,1)) + " " + QString::number(m(2,2)) + " " + QString::number(m(2,3)) + line_delim;
1158  _view += QString::number(m(3,0)) + " " + QString::number(m(3,1)) + " " + QString::number(m(3,2)) + " " + QString::number(m(3,3)) + line_delim;
1159 
1160  // Add projection matrix to output
1161  _view += QString::number(p(0,0)) + " " + QString::number(p(0,1)) + " " + QString::number(p(0,2)) + " " + QString::number(p(0,3)) + line_delim;
1162  _view += QString::number(p(1,0)) + " " + QString::number(p(1,1)) + " " + QString::number(p(1,2)) + " " + QString::number(p(1,3)) + line_delim;
1163  _view += QString::number(p(2,0)) + " " + QString::number(p(2,1)) + " " + QString::number(p(2,2)) + " " + QString::number(p(2,3)) + line_delim;
1164  _view += QString::number(p(3,0)) + " " + QString::number(p(3,1)) + " " + QString::number(p(3,2)) + " " + QString::number(p(3,3)) + line_delim;
1165 
1166  // add gl width/height, current projection Mode and the ortho mode width to output
1167  _view += QString::number(_windowSize.width()) + " " + QString::number(_windowSize.height()) + " " + QString::number(_splitterWidth)+ " " + QString::number(projectionMode_) + " " + QString::number(properties_.orthoWidth()) + line_delim;;
1168 
1169  // Add viewer size
1170  _view += QString::fromUtf8("%1 %2").arg(size().width()).arg(size().height());
1171 
1172  if (_make_c_string)
1173  _view += "\"";
1174 
1175  _view += "\n";
1176 }
1177 
1178 
1179 //----------------------------------------------------------------------------
1180 
1181 
1182 bool glViewer::decodeView(const QString& _view,
1183  ACG::GLMatrixd &m, ACG::GLMatrixd &p, int &pMode, double &ortho_width,
1184  QSize *_windowSize /*= NULL*/,
1185  int* _splitterWidth /*= NULL*/, QSize *_viewportSize)
1186 {
1187  // Remove the magic from the string
1188  QString temp = _view;
1189  temp.remove(0,sizeof(COPY_PASTE_VIEW_START_STRING));
1190 
1191  //Split it into its components
1192  QStringList split = temp.split(QRegExp("[\\n\\s]"),QString::SkipEmptyParts);
1193 
1194  // New version
1195  if ( split.size() >= 37 ) {
1196 
1197  //*********************************************************
1198  // Parse the components
1199  // first, get the projection and the modelview matrices
1200  //*********************************************************
1201  for (int i = 0; i < 4; ++i)
1202  {
1203  for (int j = 0; j < 4; ++j)
1204  {
1205  m(i,j) = split[i*4 + j].toDouble();
1206  p(i,j) = split[i*4 + j +16 ].toDouble();
1207  }
1208  }
1209 
1210  //*********************************************************
1211  //parse the window size if requested
1212  //*********************************************************
1213  if (_windowSize)
1214  {
1215  //restore the old window size
1216  int w = split[32].toInt();
1217  int h = split[33].toInt();
1218  *_windowSize = QSize(w,h);
1219  }
1220 
1221  //*********************************************************
1222  //parse the splitter width for the toolboxes if requested
1223  //*********************************************************
1224  if (_splitterWidth) {
1225  *_splitterWidth = split[34].toInt();
1226  }
1227 
1228  //*********************************************************
1229  // Projection mode and orthogonal width
1230  //*********************************************************
1231  pMode = split[35].toInt();
1232  ortho_width = split[36].toDouble();
1233 
1234  if (_viewportSize && split.size() >= 39) {
1235  *_viewportSize = QSize(split[37].toInt(), split[38].toInt());
1236  }
1237 
1238  } else if ( split.size() == 36 ) { // Old Version
1239 
1240  //*********************************************************
1241  // Parse the components
1242  // first, get the projection and the modelview matrices
1243  //*********************************************************
1244  for (int i = 0; i < 4; ++i)
1245  {
1246  for (int j = 0; j < 4; ++j)
1247  {
1248  m(i,j) = split[i*4 + j].toDouble();
1249  p(i,j) = split[i*4 + j +16].toDouble();
1250  }
1251  }
1252 
1253  //*********************************************************
1254  //parse the window size if requested
1255  //*********************************************************
1256  if (_windowSize)
1257  {
1258  //restore the old window size
1259  int w = split[32].toInt();
1260  int h = split[33].toInt();
1261  *_windowSize = QSize(w,h);
1262  }
1263 
1264 
1265  //*********************************************************
1266  // Return -1 to inform, that the value is unknown
1267  //*********************************************************
1268  if (_splitterWidth) {
1269  *_splitterWidth = -1;
1270  }
1271 
1272  //*********************************************************
1273  // Projection mode and orthogonal width
1274  //*********************************************************
1275  pMode = split[34].toInt();
1276  ortho_width = split[35].toDouble();
1277 
1278  } else { // Garbage ?!
1279  std::cerr << "Unable to paste view ... wrong parameter count!! is" << split.size() << std::endl;
1280  return false;
1281  }
1282 
1283  return true;
1284 }
1285 
1286 bool glViewer::decodeView(const QString& _view, QSize *_windowSize /*= NULL*/,
1287  int* _splitterWidth /*= NULL*/, QSize *_viewportSize)
1288 {
1289  if (_view.left(sizeof(COPY_PASTE_VIEW_START_STRING)-1) != QString(COPY_PASTE_VIEW_START_STRING))
1290  {
1291  std::cerr << "No View was copied." << std::endl;
1292  return false;
1293  }
1294 
1295  ACG::GLMatrixd m, p;
1296  int pMode;
1297  double ortho_width;
1298 
1299  if (!decodeView(_view, m, p, pMode, ortho_width,
1300  _windowSize, _splitterWidth, _viewportSize))
1301  return false;
1302  properties_.orthoWidth(ortho_width);
1303 
1304  // Switch to our gl context
1305  makeCurrent();
1306 
1307  // set projection mode
1308  if (projectionMode_ != (ProjectionMode)pMode)
1310 
1311  // Apply new modelview matrix
1312  glstate_->set_modelview(m);
1313 
1314  updateGL();
1315 
1316  return true;
1317 }
1318 
1319 
1320 //-----------------------------------------------------------------------------
1321 
1322 
1323 void glViewer::actionCopyView(const QSize &_windowSize /*= QSize(-1,-1)*/, const int _splitterWidth /*= -1*/,
1324  const bool _make_c_string /*= false*/)
1325 {
1326  QString view;
1327  encodeView(view,_windowSize,_splitterWidth, _make_c_string);
1328  QApplication::clipboard()->setText(view);
1329 }
1330 
1331 
1332 //-----------------------------------------------------------------------------
1333 
1334 
1335 void glViewer::actionPasteView(QSize * _windowSize /*= NULL*/, int *_splitterWidth /*= NULL*/)
1336 {
1337  QString view;
1338  view = QApplication::clipboard()->text();
1339  decodeView(view,_windowSize,_splitterWidth);
1340 }
1341 
1342 void glViewer::actionSetView(QString view) {
1343  decodeView(view, 0, 0);
1344 }
1345 
1346 //-----------------------------------------------------------------------------
1347 
1348 void
1349 glViewer::createWidgets()
1350 {
1351  // Construct GL context & widget
1352 
1353  wheelZ_=new ACG::QtWidgets::QtWheel( 0,"wheel-z",ACG::QtWidgets::QtWheel::Vertical);
1354  wheelZ_->setMinimumSize(wheelZ_->sizeHint());
1355  wheelZ_->setMaximumSize(wheelZ_->sizeHint());
1356  connect(wheelZ_,SIGNAL(angleChangedBy(double)),
1357  this,SLOT(slotWheelZ(double)));
1358  wheelZ_->setToolTip( tr("Translate along <b>z-axis</b>."));
1359  wheelZ_->setWhatsThis( tr("Translate along <b>z-axis</b>."));
1360 
1361  wheelY_=new ACG::QtWidgets::QtWheel( 0,"wheel-y",ACG::QtWidgets::QtWheel::Horizontal);
1362  wheelY_->setMinimumSize(wheelY_->sizeHint());
1363  wheelY_->setMaximumSize(wheelY_->sizeHint());
1364  connect(wheelY_,SIGNAL(angleChangedBy(double)),
1365  this,SLOT(slotWheelY(double)));
1366  wheelY_->setToolTip(tr("Rotate around <b>y-axis</b>."));
1367  wheelY_->setWhatsThis( tr("Rotate around <b>y-axis</b>."));
1368 
1369  wheelX_=new ACG::QtWidgets::QtWheel( 0,"wheel-x" ,ACG::QtWidgets::QtWheel::Vertical);
1370  wheelX_->setMinimumSize(wheelX_->sizeHint());
1371  wheelX_->setMaximumSize(wheelX_->sizeHint());
1372  connect(wheelX_,SIGNAL(angleChangedBy(double)),
1373  this,SLOT(slotWheelX(double)));
1374  wheelX_->setToolTip(tr("Rotate around <b>x-axis</b>."));
1375  wheelX_->setWhatsThis( tr("Rotate around <b>x-axis</b>."));
1376 
1377  // Hide or show wheels (depending on ini option)
1378  if( ! OpenFlipperSettings().value("Core/Gui/glViewer/showControlWheels").toBool() )
1379  slotHideWheels();
1380 
1381  QGraphicsWidget *wheelX = glScene_->addWidget (wheelX_);
1382  QGraphicsWidget *wheelY = glScene_->addWidget (wheelY_);
1383  QGraphicsWidget *wheelZ = glScene_->addWidget (wheelZ_);
1384 
1385  wheelX_->setWindowOpacity (0.5);
1386  wheelY_->setWindowOpacity (0.5);
1387  wheelZ_->setWindowOpacity (0.5);
1388 
1389  wheelX->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
1390  wheelY->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
1391  wheelZ->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
1392 
1393  glBaseLayout_ = new QtGLViewerLayout;
1394  glBaseLayout_->addWheelX(wheelX);
1395  glBaseLayout_->addWheelY(wheelY);
1396  glBaseLayout_->addWheelZ(wheelZ);
1397 
1398  connect(wheelX_,SIGNAL(hideWheel()),this,SLOT(slotHideWheels()));
1399  connect(wheelY_,SIGNAL(hideWheel()),this,SLOT(slotHideWheels()));
1400  connect(wheelZ_,SIGNAL(hideWheel()),this,SLOT(slotHideWheels()));
1401 
1402  setLayout(glBaseLayout_);
1403 }
1404 
1405 //-----------------------------------------------------------------------------
1406 
1407 
1408 void glViewer::translate(const ACG::Vec3d& _trans)
1409 {
1410  makeCurrent();
1411  glstate_->translate(_trans[0], _trans[1], _trans[2], ACG::MULT_FROM_LEFT);
1412 
1413  updateGL();
1414 
1415  emit viewChanged();
1416 }
1417 
1418 
1419 //-----------------------------------------------------------------------------
1420 
1421 
1423 {
1424  makeCurrent();
1426 }
1427 
1428 
1429 //-----------------------------------------------------------------------------
1430 
1431 
1432 void glViewer::rotate(const ACG::Vec3d& _axis,
1433  double _angle,
1434  const ACG::Vec3d& _center)
1435 {
1436  makeCurrent();
1437  ACG::Vec3d t = glstate_->modelview().transform_point(_center);
1438  glstate_->translate(-t[0], -t[1], -t[2], ACG::MULT_FROM_LEFT);
1439  glstate_->rotate(_angle, _axis[0], _axis[1], _axis[2], ACG::MULT_FROM_LEFT);
1440  glstate_->translate( t[0], t[1], t[2], ACG::MULT_FROM_LEFT);
1441 
1442  updateGL();
1443 
1444  emit viewChanged();
1445 }
1446 
1447 
1448 //-----------------------------------------------------------------------------
1449 
1450 
1451 unsigned int glViewer::glWidth() const {
1452  return size().width();
1453 }
1454 unsigned int glViewer::glHeight() const {
1455  return size().height();
1456 }
1457 QSize glViewer::glSize() const {
1458  return QSize(size().width(),size().height());
1459 }
1460 QPoint glViewer::glMapFromGlobal( const QPoint& _pos ) const {
1461  QPoint p (scene()->views().front()->mapFromGlobal(_pos));
1462  QPointF f (mapFromScene(QPointF(p.x(), p.y ())));
1463  return QPoint (f.x(), f.y());
1464 }
1465 
1466 QPoint glViewer::glMapToGlobal( const QPoint& _pos ) const {
1467  QPointF f (mapToScene(QPointF(_pos.x(), _pos.y ())));
1468  QPoint p (f.x(), f.y());
1469  return scene()->views().front()->mapToGlobal(p);
1470 }
1471 
1472 double glViewer::field_of_view_vertical() const {
1473  return OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble()
1474  + fovyModifier_;
1475 }
1476 
1477 
1478 //-----------------------------------------------------------------------------
1479 
1480 
1481 void glViewer::slotWheelX(double _dAngle)
1482 {
1484  updateGL();
1485 
1486  emit viewChanged();
1487 }
1488 
1489 void glViewer::slotWheelY(double _dAngle)
1490 {
1492  updateGL();
1493 
1494  emit viewChanged();
1495 }
1496 
1497 void glViewer::slotWheelZ(double _dist)
1498 {
1499  double dz = _dist * 0.5 / M_PI * properties_.sceneRadius() * 2.0;
1500  translate(ACG::Vec3d(0,0,dz));
1501  updateGL();
1502 
1503  emit viewChanged();
1504 }
1505 
1506 //-----------------------------------------------------------------------------
1507 
1508 
1510 {
1511  glareaGrabbed_ = true;
1512 
1513  if (properties_.cursorPainter()) {
1514  properties_.cursorPainter()->setCursor(Qt::BlankCursor);
1515  std::cerr << "grabGLArea: Blanking cursorpainter cursor" << std::endl;
1516  } else {
1517  setCursor(Qt::BlankCursor);
1518  std::cerr << "grabGLArea: Blanking qt cursor" << std::endl;
1519  }
1520  grabMouse();
1521  grabKeyboard();
1522 }
1523 
1525 {
1526  glareaGrabbed_ = false;
1527 
1528  ungrabMouse();
1529  ungrabKeyboard();
1530 
1531  if (properties_.cursorPainter()) {
1532  properties_.cursorPainter()->setCursor(Qt::ArrowCursor);
1533  std::cerr << "grabGLArea: Setting cursorPainter cursor to arrow" << std::endl;
1534  } else {
1535  setCursor(Qt::ArrowCursor);
1536  std::cerr << "grabGLArea: Setting qt cursor to arrow" << std::endl;
1537  }
1538 }
1539 
1540 
1541 //-----------------------------------------------------------------------------
1542 
1543 
1544 void glViewer::contextMenuEvent(QGraphicsSceneContextMenuEvent* _e)
1545 {
1546  emit signalMakeActive();
1547  glScene_->update ();
1548 
1549  QPoint p (_e->pos().x(), _e->pos().y());
1551 }
1552 
1553 
1554 //-----------------------------------------------------------------------------
1555 
1556 void glViewer::mousePressEvent(QGraphicsSceneMouseEvent* _e)
1557 {
1558  makeCurrent();
1559  QPoint p (_e->scenePos().x(), _e->scenePos().y());
1560  QMouseEvent me(QEvent::MouseButtonPress ,p, _e->screenPos(), _e->button(),
1561  _e->buttons(), _e->modifiers());
1562  _e->accept ();
1563 
1564  emit signalMakeActive();
1565  const GLuint prevFBO = ACG::GLState::getFramebufferDraw();
1566 
1567  //recreate FBO if gl area was resized
1568  if (mouseCache_ != nullptr && QFBOResized(mouseCache_))
1569  {
1570  deleteQFBO(mouseCache_);
1571  mouseCache_ = nullptr;
1572  }
1573 
1574  if (mouseCache_ == nullptr)
1575  {
1576  GLuint fboHandle;
1577  int samples = 0;
1578  createQFBO(mouseCache_, &fboHandle, glWidth() , glHeight(), &samples);
1579  }
1580 
1581  bindQFBO(mouseCache_);
1582 
1583  glScene_->update ();
1584 
1585  // right button pressed => popup menu (ignore here)
1586  if (allowConstrainedRotation() || _e->button() != Qt::RightButton )
1587  {
1588  switch (properties_.actionMode())
1589  {
1590  case Viewer::ExamineMode:
1591  if ((_e->modifiers() & Qt::ControlModifier)) // drag&drop
1592  emit startDragEvent( &me );
1593  else
1594  viewMouseEvent(&me); // examine
1595 
1596  if (clickTimer_.isActive ())
1597  {
1598  clickTime_ = QTime ();
1599  clickTimer_.stop ();
1600  }
1601  else
1602  {
1603  clickTime_.start ();
1604  clickEvent_ = me;
1605  }
1606  break;
1607 
1608  case Viewer::LightMode:
1609  emit(signalMouseEventLight(&me));
1610  break;
1611 
1612  case Viewer::PickingMode: // give event to application
1613  emit(signalMouseEvent(&me, properties_.pickMode() ));
1614  emit(signalMouseEvent(&me));
1615  break;
1616 
1617  case Viewer::QuestionMode: // give event to application
1618  emit(signalMouseEventIdentify(&me));
1619  break;
1620  }
1621  }
1622  //restore old FBO
1623  ACG::GLState::bindFramebuffer(GL_FRAMEBUFFER_EXT,prevFBO);
1624 }
1625 
1626 
1627 //-----------------------------------------------------------------------------
1628 
1629 
1630 void glViewer::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* _e)
1631 {
1632  QPoint p (_e->scenePos().x(), _e->scenePos().y());
1633  QMouseEvent me(QEvent::MouseButtonDblClick ,p, _e->screenPos(), _e->button(),
1634  _e->buttons(), _e->modifiers());
1635  _e->accept ();
1636 
1637  emit signalMakeActive();
1638  glScene_->update ();
1639 
1640  switch (properties_.actionMode())
1641  {
1642  case Viewer::ExamineMode:
1643  viewMouseEvent(&me);
1644  emit signalMouseEventClick (&me, true);
1645  break;
1646 
1647  case Viewer::LightMode:
1648  emit(signalMouseEventLight(&me));
1649  break;
1650 
1651  case Viewer::PickingMode: // give event to application
1652  emit(signalMouseEvent(&me, properties_.pickMode() ));
1653  emit(signalMouseEvent(&me));
1654  break;
1655 
1656  case Viewer::QuestionMode: // give event to application
1657  emit(signalMouseEventIdentify(&me));
1658  break;
1659  }
1660 }
1661 
1662 
1663 //-----------------------------------------------------------------------------
1664 
1665 
1666 void glViewer::mouseMoveEvent(QGraphicsSceneMouseEvent* _e)
1667 {
1668  QPoint p (_e->scenePos().x(), _e->scenePos().y());
1669  QMouseEvent me(QEvent::MouseMove ,p, _e->screenPos(), _e->button(),
1670  _e->buttons(), _e->modifiers());
1671  _e->accept();
1672 
1673  switch ( properties_.actionMode() )
1674  {
1675  case Viewer::ExamineMode:
1676  viewMouseEvent(&me);
1677  break;
1678 
1679  case Viewer::LightMode:
1680  emit(signalMouseEventLight(&me));
1681  break;
1682 
1683  case Viewer::PickingMode:
1684  // give event to application
1685  // deliver mouse moves with no button down, if tracking is enabled,
1686  if ((_e->buttons() & (Qt::LeftButton | Qt::MidButton | Qt::RightButton))
1687  || trackMouse_)
1688  {
1689  emit(signalMouseEvent(&me, properties_.pickMode() ));
1690  emit(signalMouseEvent(&me));
1691  }
1692  break;
1693 
1694  case Viewer::QuestionMode: // give event to application
1695  emit(signalMouseEventIdentify(&me));
1696  break;
1697 
1698  default: // avoid warning
1699  break;
1700  }
1701 }
1702 
1703 //-----------------------------------------------------------------------------
1704 
1705 
1706 void glViewer::mouseReleaseEvent(QGraphicsSceneMouseEvent* _e)
1707 {
1708  QPoint p (_e->scenePos().x(), _e->scenePos().y());
1709  QMouseEvent me(QEvent::MouseButtonRelease ,p, _e->screenPos(), _e->button(),
1710  _e->buttons(), _e->modifiers());
1711  _e->accept();
1712 
1713 // if (_event->button() == Qt::RightButton )
1714 // hidePopupMenus();
1715 
1716  if (_e->button() != Qt::RightButton || (properties_.actionMode() == Viewer::PickingMode) )
1717  {
1718  switch ( properties_.actionMode() )
1719  {
1720  case Viewer::ExamineMode:
1721  viewMouseEvent(&me);
1722 
1723  if (!clickTime_.isNull ())
1724  {
1725  int elapsed = clickTime_.elapsed ();
1726  QPoint diff = clickEvent_.pos () - me.pos ();
1727 
1728  if (abs (diff.x ()) <= 1 && abs (diff.y ()) <= 1 && elapsed <= QApplication::doubleClickInterval () / 2)
1729  {
1730  clickTimer_.setSingleShot (true);
1731  clickTimer_.setInterval (QApplication::doubleClickInterval () - elapsed);
1732  clickTimer_.start ();
1733  }
1734  else
1735  {
1736  clickTime_ = QTime ();
1737  clickTimer_.stop ();
1738  }
1739  }
1740  break;
1741 
1742  case Viewer::LightMode:
1743  emit(signalMouseEventLight(&me));
1744  break;
1745 
1746  case Viewer::PickingMode: // give event to application
1747  emit(signalMouseEvent(&me, properties_.pickMode() ));
1748  emit(signalMouseEvent(&me));
1749  break;
1750 
1751  case Viewer::QuestionMode: // give event to application
1752  emit(signalMouseEventIdentify(&me));
1753  break;
1754 
1755  default: // avoid warning
1756  break;
1757  }
1758  }
1759 
1760  isRotating_ = false;
1761 }
1762 
1763 
1764 //-----------------------------------------------------------------------------
1765 
1766 
1767 void glViewer::wheelEvent(QGraphicsSceneWheelEvent* _e)
1768 {
1769  QPoint p (_e->scenePos().x(), _e->scenePos().y());
1770  QWheelEvent we(p, _e->screenPos(), _e->delta(), _e->buttons(),
1771  _e->modifiers(), _e->orientation());
1772  _e->accept();
1773 
1774  switch ( properties_.actionMode() )
1775  {
1776  case Viewer::ExamineMode:
1777  viewWheelEvent(&we);
1778  break;
1779 
1780  case Viewer::PickingMode: // give event to application
1781  emit(signalWheelEvent(&we, properties_.pickMode() ));
1782  break;
1783 
1784  default: // avoid warning
1785  break;
1786  }
1787 
1788  isRotating_ = false;
1789 }
1790 
1791 //-----------------------------------------------------------------------------
1792 
1793 void glViewer::dragEnterEvent(QGraphicsSceneDragDropEvent* _e)
1794 {
1795  std::cerr << "dragEnter" << std::endl;
1796 
1797  QPoint p (_e->pos().x(), _e->pos().y());
1798  QDragEnterEvent de(p, _e->possibleActions(), _e->mimeData(), _e->buttons(),
1799  _e->modifiers ());
1800  emit dragEnterEvent(&de);
1801  _e->accept();
1802 }
1803 
1804 //-----------------------------------------------------------------------------
1805 
1806 
1807 void glViewer::dropEvent(QGraphicsSceneDragDropEvent* _e)
1808 {
1809  std::cerr << "drop" << std::endl;
1810 
1811  QPoint p (_e->pos().x(), _e->pos().y());
1812  QDropEvent de(p, _e->possibleActions(), _e->mimeData(), _e->buttons(),
1813  _e->modifiers ());
1814  emit dropEvent(&de);
1815  _e->accept();
1816 }
1817 
1818 //-----------------------------------------------------------------------------
1819 
1820 
1821 void glViewer::viewMouseEvent(QMouseEvent* _event) {
1822 
1823  if (navigationMode_ == NORMAL_NAVIGATION) {
1824 
1825  handleNormalNavigation(_event);
1826 
1827  } else if (navigationMode_ == FIRSTPERSON_NAVIGATION) {
1828 
1830  }
1831 
1832 }
1833 
1834 //----------------------------------------------------------------------------
1835 
1836 void glViewer::handleFirstPersonNavigation( QMouseEvent* _event) {
1837 
1838  // Ego-shooter navigation mode is selected
1839  QPointF f(mapFromScene(QPointF(_event->pos().x(), _event->pos().y())));
1840  QPoint pos(f.x(), f.y());
1841 
1842  switch (_event->type()) {
1843 
1844  case QEvent::MouseButtonPress: {
1845  lastPoint2D_ = pos;
1846  lookAround_ = true;
1847  break;
1848  }
1849 
1850  case QEvent::MouseButtonDblClick: {
1851  flyTo(_event->pos(), _event->button() == Qt::MidButton);
1852  break;
1853  }
1854 
1855  case QEvent::MouseMove: {
1856 
1857  if(!lookAround_) break;
1858 
1859  // Considering center point of screen as origin
1860  QPoint newpos = QPoint(pos.x() - glWidth() / 2, glHeight() / 2 - pos.y());
1861  QPoint oldpos = QPoint(lastPoint2D_.x() - glWidth() / 2, glHeight() / 2 - lastPoint2D_.y());
1862 
1863  double x = 2.0 * newpos.x() / glWidth();
1864  double y = 2.0 * newpos.y() / glHeight();
1865 
1866  double xo = 2.0 * oldpos.x() / glWidth();
1867  double yo = 2.0 * oldpos.y() / glHeight();
1868 
1869  double diffx = xo - x;
1870  double diffy = yo - y;
1871 
1874 
1875  rotate(yaxis, -diffx * 90, glstate_->eye());
1876  rotate(xaxis, diffy * 90, glstate_->eye());
1877 
1878  lastPoint2D_ = pos;
1879 
1880  updateGL();
1881  lastMoveTime_.restart();
1882 
1883  emit viewChanged();
1884 
1885  break;
1886  }
1887 
1888  case QEvent::MouseButtonRelease: {
1889  lookAround_ = false;
1890  break;
1891  }
1892 
1893  default: // avoid warning
1894  break;
1895  }
1896 }
1897 
1898 //----------------------------------------------------------------------------
1899 
1900 void glViewer::handleNormalNavigation( QMouseEvent* _event ) {
1901 
1902  makeCurrent();
1903  // Normal navigation mode is selected
1904  QPointF f(mapFromScene(QPointF(_event->pos().x(), _event->pos().y())));
1905  QPoint pos(f.x(), f.y());
1906 
1907  switch (_event->type()) {
1908 
1909  case QEvent::MouseButtonPress: {
1910 
1911  // Get the depth at the current mouse position ( projected )
1912  // This is used to do the translation in world coordinates
1913  // As the scene is rendered, we can get the depth directly from the framebuffer.
1914  GLfloat depth[1];
1915  GLint x2d = f.x() - scenePos().x();
1916  GLint y2d = glHeight() - (f.y() - scenePos().y());
1917  glReadPixels (x2d, y2d, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, depth);
1918  startDepth_ = depth[0];
1919 
1920  // shift key -> set rotation center
1921  if (_event->modifiers() & Qt::ShiftModifier) {
1922  ACG::Vec3d c;
1923  if (fast_pick(pos, c)) {
1925  properties_.trackballRadius( std::max(properties_.sceneRadius(), (c - glstate_->eye()).norm() * 0.9f) );
1926  }
1927  }
1928 
1930  lastPoint2D_ = pos;
1931  isRotating_ = true;
1932  timer_->stop();
1933 
1934  break;
1935  }
1936 
1937  case QEvent::MouseButtonDblClick: {
1938  flyTo(_event->pos(), _event->button() == Qt::MidButton);
1939  break;
1940  }
1941 
1942  case QEvent::MouseMove: {
1943  double factor = 1.0;
1944 
1945  if (_event->modifiers() == Qt::ShiftModifier)
1946  factor = properties_.wheelZoomFactorShift();
1947 
1948  // mouse button should be pressed
1949  if (_event->buttons() & (Qt::LeftButton | Qt::MidButton | Qt::RightButton)) {
1950  QPoint newPoint2D = pos;
1951 
1952  ACG::Vec3d newPoint3D;
1953  bool newPoint_hitSphere = mapToSphere(newPoint2D, newPoint3D);
1954 
1955  makeCurrent();
1956 
1957  // Left and middle button are pressed:
1958  // Translate along image planes normal direction -> zoom
1959  if ((_event->buttons() & Qt::LeftButton) && (_event->buttons() & Qt::MidButton)) {
1960  switch (projectionMode()) {
1961  case PERSPECTIVE_PROJECTION: {
1962  double value_y = properties_.sceneRadius() * ((newPoint2D.y() - lastPoint2D_.y())) * 3.0 / (double) glHeight();
1963  translate(ACG::Vec3d(0.0, 0.0, value_y * factor));
1964  updateGL();
1965  emit viewChanged();
1966  break;
1967  }
1968 
1969  case ORTHOGRAPHIC_PROJECTION: {
1970  double value_y = ((newPoint2D.y() - lastPoint2D_.y())) * properties_.orthoWidth() / (double) glHeight();
1971  properties_.orthoWidth( properties_.orthoWidth() - value_y * factor );
1973  updateGL();
1974  emit viewChanged();
1975  break;
1976  }
1977  }
1978  }
1979 
1980  // Middle button is pressed or if rotation is locked, left button can also be used
1981  // translation parallel to image plane
1982  // If an object was hit when the user started the translation,
1983  // the depth to the object is used to calculate the right translation vectors
1984  // such that the hitpoint stays below the mouse.
1985  else if ((_event->buttons() & Qt::MidButton) || (!allowRotation_ && (_event->buttons() & Qt::LeftButton)) ) {
1986 
1987  ACG::Vec3d translation;
1988 
1989 
1990  // if start depth is 1, no object was hit when starting translation
1991  if ( startDepth_ == 1 && projectionMode() != ORTHOGRAPHIC_PROJECTION ) {
1992  double value_x = properties_.sceneRadius() * ((newPoint2D.x() - lastPoint2D_.x())) * 2.0 / (double) glWidth();
1993  double value_y = properties_.sceneRadius() * ((newPoint2D.y() - lastPoint2D_.y())) * 2.0 / (double) glHeight();
1994  translation = ACG::Vec3d(value_x * factor, -value_y * factor, 0.0);
1995 
1996  } else {
1997  // Get the new mouse position in GL coordinates
1998  GLint x2dEnd = newPoint2D.x() - scenePos().x();
1999  GLint y2dEnd = glHeight() - (newPoint2D.y() - scenePos().y());
2000 
2001  // Get the last mouse position in GL coordinates
2002  GLint x2dStart = lastPoint2D_.x() - scenePos().x();
2003  GLint y2dStart = glHeight() - (lastPoint2D_.y() - scenePos().y());
2004 
2005  // unproject both to get translation vector
2006  ACG::Vec3d projectedStart(float(x2dStart),float(y2dStart),startDepth_);
2007  ACG::Vec3d projectedEnd(float(x2dEnd),float(y2dEnd),startDepth_);
2008  ACG::Vec3d unprojectedStart = glstate_->unproject(projectedStart);
2009  ACG::Vec3d unprojectedEnd = glstate_->unproject(projectedEnd);
2010 
2011  // calculate the difference and transform it with the modelview to get the right translation
2012  translation = unprojectedEnd - unprojectedStart;
2013  translation = glstate_->modelview().transform_vector(translation);
2014  }
2015 
2016  translate(translation);
2017 
2018  // left button pressed:
2019  // rotate the scene if rotation is not locked
2020  } else if (allowRotation_ && (_event->buttons() & Qt::LeftButton)) {
2021  ACG::Vec3d axis(1.0, 0.0, 0.0);
2022  double angle(0.0);
2023 
2024  if (lastPoint_hitSphere_) {
2025 
2026  if ((newPoint_hitSphere = mapToSphere(newPoint2D, newPoint3D))) {
2027  axis = lastPoint3D_ % newPoint3D;
2028  double cos_angle = (lastPoint3D_ | newPoint3D);
2029  if (fabs(cos_angle) < 1.0) {
2030  angle = acos(cos_angle) * 180.0 / M_PI * factor;
2031  angle *= 2.0; // inventor rotation
2032  }
2033  }
2034 
2035  rotate(axis, angle);
2036 
2037  }
2038 
2039  lastRotationAxis_ = axis;
2040  lastRotationAngle_ = angle;
2041  } else if (allowConstrainedRotation() && (_event->buttons() & Qt::RightButton)) {
2042  //ACG::Vec3d axis(constrainedRotationAxis_);
2043  //double angle(0.0);
2044 
2045  if (lastPoint_hitSphere_) {
2046 
2047  const QPoint dragVector = newPoint2D - lastPoint2D_;
2048  const double dragLength = dragVector.y();
2049  //ACG::Vec2d(dragVector.x(), dragVector.y()).norm();
2050  const double angle = -dragLength * factor;
2051 
2052  /*
2053  {
2054  makeCurrent();
2055  const ACG::Vec3d center =
2056  properties_.trackballCenter();
2057  const ACG::Vec3d t =
2058  startViewMatrix_.transform_point(center);
2059  glstate_->set_modelview(startViewMatrix_);
2060  glstate_->translate(-t[0], -t[1], -t[2],
2061  ACG::MULT_FROM_LEFT);
2062  glstate_->rotate(angle,
2063  constrainedRotationAxis_[0],
2064  constrainedRotationAxis_[1],
2065  constrainedRotationAxis_[2],
2066  ACG::MULT_FROM_LEFT);
2067  glstate_->translate(t[0], t[1], t[2],
2068  ACG::MULT_FROM_LEFT);
2069  }
2070  */
2071  ACG::Vec3d center(glWidth()/2.0, glHeight()/2.0, 0);
2072  rotate(constrainedRotationAxis_, angle, unproject(center));
2073 
2075  lastRotationAngle_ = angle;
2076  }
2077  }
2078 
2079  lastPoint2D_ = newPoint2D;
2080  lastPoint3D_ = newPoint3D;
2081  lastPoint_hitSphere_ = newPoint_hitSphere;
2082 
2083  updateGL();
2084  lastMoveTime_.restart();
2085  emit viewChanged();
2086  }
2087  break;
2088  }
2089 
2090  case QEvent::MouseButtonRelease: {
2091  lastPoint_hitSphere_ = false;
2092 
2093  // continue rotation ?
2094  if (isRotating_ && (_event->button() == Qt::LeftButton) && (!(_event->buttons() & Qt::MidButton))
2095  && (lastMoveTime_.elapsed() < 50) && properties_.animation())
2096  timer_->start(0);
2097  break;
2098  }
2099 
2100  default: // avoid warning
2101  break;
2102  }
2103 }
2104 
2105 //-----------------------------------------------------------------------------
2106 
2107 void glViewer::viewWheelEvent( QWheelEvent* _event)
2108 {
2109 
2110  // Default mouse wheel factor
2111  double factor = properties_.wheelZoomFactor();
2112 
2113  // Shift pressed, so we use the smaller factor
2114  if (_event->modifiers() == Qt::ShiftModifier)
2115  factor = properties_.wheelZoomFactorShift();
2116 
2117  // Mouse wheel inversion
2118  if (properties_.wheelInvert())
2119  factor *= -1.0;
2120 
2122  {
2123 
2124  // Control key : Modify field of view. Otherwise translate
2125  if ( _event->modifiers() & Qt::ControlModifier ) {
2126 
2127  // Most mouse types work in steps of 15 degrees, in which case the delta value is a
2128  // multiple of 120; i.e., 120 units * 1/8 = 15 degrees
2129  double numDegrees = double(_event->delta()) / 8.0;
2130  double numSteps = numDegrees / 15.0;
2131 
2132  // Update the fovy modifier
2133  // This modifier will be added to the default fov to get the zoom
2134  fovyModifier_ += numSteps * factor ;
2135 
2136  // Clamp to minimum
2137  if ( (OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble() + fovyModifier_) < 1.0 )
2138  fovyModifier_ = 1.0 -OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble();
2139 
2140  // Clamp to maximum
2141  if ( (OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble() + fovyModifier_) > 179.0 )
2142  fovyModifier_ = 179.0-OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble();
2143  } else {
2144 
2145 
2146  // Old style zoom (bad as it does not modify the projection but the modelview,
2147  // which kills e.g. Sky Boxes
2148  double d = -(double)_event->delta() / 120.0 * 0.2 * factor * properties_.trackballRadius() / 3.0;
2149  translate( ACG::Vec3d(0.0, 0.0, d) );
2150  }
2151 
2152 
2153 
2154  updateGL();
2155  }
2156  else
2157  {
2158  double d = (double)_event->delta() / 120.0 * 0.2 * factor * properties_.orthoWidth();
2160 
2161 
2163  updateGL();
2164  }
2165 
2166  emit viewChanged();
2167 }
2168 
2169 
2170 //-----------------------------------------------------------------------------
2171 
2172 
2173 bool glViewer::mapToSphere(const QPoint& _v2D, ACG::Vec3d& _v3D) const
2174 {
2175  if ( (_v2D.x() >= 0) && (_v2D.x() < (int)glWidth()) &&
2176  (_v2D.y() >= 0) && (_v2D.y() < (int)glHeight()) )
2177  {
2178  double x = (double)(_v2D.x() - ((double)glWidth() / 2.0)) / (double)glWidth();
2179  double y = (double)(((double)glHeight() / 2.0) - _v2D.y()) / (double)glHeight();
2180  double sinx = sin(M_PI * x * 0.5);
2181  double siny = sin(M_PI * y * 0.5);
2182  double sinx2siny2 = sinx * sinx + siny * siny;
2183 
2184  _v3D[0] = sinx;
2185  _v3D[1] = siny;
2186  _v3D[2] = sinx2siny2 < 1.0 ? sqrt(1.0 - sinx2siny2) : 0.0;
2187 
2188  return true;
2189  }
2190  else return false;
2191 }
2192 
2193 
2194 //-----------------------------------------------------------------------------
2195 
2196 
2198 {
2199  makeCurrent();
2201  updateGL();
2202 
2203  if (!properties_.updateLocked()) {
2204 
2205  static int msecs=0, count=0;
2206 
2207  msecs += frame_time_;
2208  if (count >= 10 && msecs >= 500) {
2209  char s[100];
2210  sprintf( s, "%.3f fps", (1000.0 * count / (float)msecs) );
2211  emit statusMessage(s,2000);
2212  count = msecs = 0;
2213  }
2214  else
2215  ++count;
2216  }
2217 }
2218 
2220 
2222 
2224 
2226 
2227  if (properties_.isCCWFront() )
2228  glFrontFace( GL_CCW );
2229  else
2230  glFrontFace( GL_CW );
2231 
2232  if ( properties_.backFaceCulling() )
2233  ACG::GLState::enable( GL_CULL_FACE );
2234  else
2235  ACG::GLState::disable( GL_CULL_FACE );
2236 
2237  // Make sure the right buffer is used in non stereo setup
2238  makeCurrent();
2239  ACG::GLState::drawBuffer(ACG::GLState::getFramebufferDraw() ? GL_COLOR_ATTACHMENT0 : GL_BACK);
2240 
2241  // Required for stereo toggling
2243 }
2244 
2246  makeCurrent();
2247  applyProperties();
2248  updateGL();
2249 }
2250 
2251 void glViewer::snapshot(QImage& _image, int _width, int _height, bool _alpha, bool _hideCoordsys, int samples) {
2252  makeCurrent();
2253 
2254  int w = 0, h = 0, bak_w = 0, bak_h = 0, left = 0, bottom = 0;
2255 
2258 
2259  // Get viewport data
2260  glstate_->get_viewport(left, bottom, w, h);
2261  double aspect = (double)w / (double)h;
2262 
2263  // Test if size is given:
2264  if(_width != 0 || _height != 0) {
2265 
2266  // Adapt dimensions if aspect ratio is demanded
2267  if(_width == 0) {
2268  _width = (int)((double)_height * aspect);
2269  }
2270  if(_height == 0) {
2271  _height = (int)((double)_width / aspect);
2272  }
2273  bak_w = w;
2274  bak_h = h;
2275  w = _width;
2276  h = _height;
2277 
2278  // Set new viewport
2279  glstate_->viewport(0, 0, w, h);
2280  aspect = (double)w / (double)h;
2281  }
2282 
2283  QFramebufferObject* fb = nullptr;
2284  GLuint hnd;
2285 
2286  if ( createQFBO(fb,&hnd,w,h,&samples) ){
2287 
2288  const GLuint prevFbo = ACG::GLState::getFramebufferDraw();
2289 
2290  ACG::GLState::bindFramebuffer(GL_FRAMEBUFFER_EXT, hnd);
2291 
2292  // Turn alpha on if demanded
2293  ACG::Vec4f backColorBak;
2294  ACG::Vec4f newBack;
2295 
2296  bool formerCoordsysState = true;
2297  // Hide coordsys node if demanded
2298  if(_hideCoordsys) {
2299  // Find coordsys node
2300  ACG::SceneGraph::BaseNode* node = 0;
2301  node = sceneGraphRoot_->find("Core Coordsys Node");
2302  if(node != 0) {
2303  formerCoordsysState = node->visible();
2304  node->hide();
2305  } else {
2306  emit statusMessage(QString(tr("Could not find coordsys node, thus it will appear in the snapshot anyway.")));
2307  }
2308  }
2309 
2310  backColorBak = properties()->backgroundColor();
2311 
2312  newBack = ACG::Vec4f(backColorBak[0], backColorBak[1], backColorBak[2], (_alpha ? 0.0f : 1.0f));
2313  properties()->backgroundColor(newBack);
2314 
2315  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2316 
2317  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2318 
2319  // adjust blend function for alpha channel
2320  ACG::GLState::blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE);
2322 
2323  glEnable(GL_MULTISAMPLE);
2324  paintGL(aspect);
2325  glFinish();
2326 
2328 
2329  glDisable(GL_MULTISAMPLE);
2330 
2331  //Qt FrameBuffer "toImage" function returns QImage::Format_ARGB32_Premultiplied. not desired
2332  QFramebufferObject* temp = nullptr;
2333  GLuint tempHnd;
2334  int testSamples = -1;
2335  createQFBO(temp, &tempHnd, w, h, &testSamples);
2336  if (samples != 0)
2337  {
2338  //cannot directly read from a multisampled framebuffer.
2339  //create new one without sampling and read from it
2340  QRect rect(QPoint(0, 0), QSize(w,h));
2341 
2342  blitQFBO(temp, rect, fb, rect);
2343  ACG::GLState::bindFramebuffer(GL_FRAMEBUFFER_EXT, tempHnd);
2344  }
2345 
2346  //get the framebuffer data
2347  _image = QImage(w,h,QImage::Format_ARGB32);
2348  glReadPixels(0,0,w,h,GL_BGRA,GL_UNSIGNED_INT_8_8_8_8_REV,reinterpret_cast<void*>(_image.bits()));
2349  _image = _image.mirrored(false,true);//convert from opengl to qt coordinates
2350 
2351 
2352  //cleanup
2353  ACG::GLState::bindFramebuffer(GL_FRAMEBUFFER_EXT, prevFbo);
2354 
2355  // Reset alpha settings
2356  if(_alpha)
2357  properties()->backgroundColor(backColorBak);
2358 
2359  if(_hideCoordsys) {
2360  // Find coordsys node
2361  ACG::SceneGraph::BaseNode* node = 0;
2362  node = sceneGraphRoot_->find("Core Coordsys Node");
2363  if(node != 0 && formerCoordsysState) {
2364  node->show();
2365  }
2366  }
2367 
2368  deleteQFBO(temp);
2369  }
2370 
2371  deleteQFBO(fb);
2372 
2373 
2374  if(_width != 0 || _height != 0) {
2375  // Reset viewport to former size
2376  glstate_->viewport(left, bottom, bak_w, bak_h);
2377  }
2378 
2381 }
2382 
2383 
2384 void glViewer::snapshot( int _width, int _height, bool _alpha, bool _hideCoordsys, int samples)
2385 {
2386  QImage image;
2387 
2388  // Capture image
2389  snapshot(image, _width, _height, _alpha, _hideCoordsys, samples);
2390 
2391  /*
2392  * Meta data
2393  */
2394  QString comments = PluginFunctions::collectObjectComments(true, false).join("\n");
2395  if (!comments.isEmpty())
2396  image.setText("Mesh Comments", comments);
2397  QString view;
2398  encodeView(view);
2399  image.setText("View", view);
2400 
2401  QFileInfo fi(properties_.snapshotName());
2402 
2403  QString fname = fi.path() + QDir::separator() +fi.baseName() + "." + QString::number(properties_.snapshotCounter()).rightJustified(7,'0') + "." + properties_.snapshotFileType().toLower();
2404 
2405  QImageWriter writer(fname);
2406  writer.setFormat(properties_.snapshotFileType().simplified().toLatin1());
2407 
2408  bool rval = writer.canWrite();
2409  if (rval)
2410  writer.write(image);
2411 
2412  if (rval)
2413  emit statusMessage (QString(tr("Snapshot: "))+fname,5000);
2414  else
2415  emit statusMessage (QString(tr("Could not save snapshot to ")) + fname + QString(tr(" Error: ")) + writer.errorString() );
2416 }
2417 
2418 void glViewer::slotHideWheels() {
2419  if (isVisible())
2420  {
2421  wheelX_->hide();
2422  wheelY_->hide();
2423  wheelZ_->hide();
2424  }
2425  else
2426  {
2427  show ();
2428  wheelX_->hide();
2429  wheelY_->hide();
2430  wheelZ_->hide();
2431  hide ();
2432  }
2433 }
2434 
2435 void glViewer::slotShowWheels() {
2436  if (isVisible())
2437  {
2438  wheelX_->show();
2439  wheelY_->show();
2440  wheelZ_->show();
2441  }
2442  else
2443  {
2444  show ();
2445  wheelX_->show();
2446  wheelY_->show();
2447  wheelZ_->show();
2448  hide ();
2449  }
2450 }
2451 
2452 bool glViewer::wheelsVisible() {
2453  // TODO: Return valid values
2454  return true;
2455 }
2456 
2457 //-----------------------------------------------------------------------------
2458 
2460 {
2461  emit signalMouseEventClick (&clickEvent_, false);
2462 }
2463 
2464 //-----------------------------------------------------------------------------
2465 
2467 {
2468  properties_.cursorPainter( _cursorPainter );
2469 }
2470 
2471 //-----------------------------------------------------------------------------
2472 
2473 void glViewer::updateCursorPosition (QPointF _scenePos)
2474 {
2475  if (!initialized_ || !sceneGraphRoot_ || !isVisible ())
2476  return;
2477 
2478  ACG::Vec3d tmp;
2479 
2480  size_t nodeIdx = 0;
2481  size_t targetIdx = 0;
2482 
2483 
2484  // ignore cursor if we are outside of our window
2485  if (!mapRectToScene(boundingRect ()).intersects (properties_.cursorPainter()->cursorBoundingBox().translated(_scenePos)))
2486  {
2488  }
2489  // only do real pick in stereo mode
2490  else if ( properties_.stereo() && OpenFlipperSettings().value("Core/Gui/glViewer/stereoMousePick",true).toBool() &&
2491  pick (ACG::SceneGraph::PICK_ANYTHING, _scenePos.toPoint(), nodeIdx, targetIdx, &tmp))
2492  {
2493  // the point we get back will contain the view transformation and we have to revert it
2496  }
2497  // only do real pick in stereo mode
2498  else
2499  {
2501 
2502  // reset modelview to ignore the view transformation
2504 
2505  // Project the depth value of the stereo mode zero paralax plane.
2506  // We need to use this depth to to get the cursor exactly on zero paralax plane in stereo mode
2507  double zerop = properties_.nearPlane() + ((properties_.farPlane() - properties_.nearPlane()) * OpenFlipperSettings().value("Core/Stereo/FocalLength").toDouble() );
2508  ACG::Vec3d zerod = glstate_->project (ACG::Vec3d (0.0, 0.0, -zerop));
2509 
2510  // unproject the cursor into the scene
2511  properties_.cursorPoint3D( glstate_->unproject (ACG::Vec3d (_scenePos.x(), scene()->height () - _scenePos.y(), zerod[2])) );
2512 
2514 
2516  }
2517 }
2518 
2519 //-----------------------------------------------------------------------------
2520 
2521 
2523  if(navigationMode_ == FIRSTPERSON_NAVIGATION) {
2524 
2526 
2527  dir *= -0.1;
2528 
2529  glstate_->translate(dir[0], dir[1], dir[2]);
2530 
2531  updateGL();
2532  lastMoveTime_.restart();
2533 
2534  emit viewChanged();
2535  }
2536 }
2537 
2539  if(navigationMode_ == FIRSTPERSON_NAVIGATION) {
2541 
2542  dir *= 0.1;
2543 
2544  glstate_->translate(dir[0], dir[1], dir[2]);
2545 
2546  updateGL();
2547  lastMoveTime_.restart();
2548 
2549  emit viewChanged();
2550  }
2551 }
2552 
2554  if(navigationMode_ == FIRSTPERSON_NAVIGATION) {
2555  ACG::Vec3d dir = glstate_->right();
2556 
2557  dir *= 0.1;
2558 
2559  glstate_->translate(dir[0], dir[1], dir[2]);
2560 
2561  updateGL();
2562  lastMoveTime_.restart();
2563 
2564  emit viewChanged();
2565  }
2566 }
2567 
2569  if(navigationMode_ == FIRSTPERSON_NAVIGATION) {
2570  ACG::Vec3d dir = glstate_->right();
2571 
2572  dir *= -0.1;
2573 
2574  glstate_->translate(dir[0], dir[1], dir[2]);
2575 
2576  updateGL();
2577  lastMoveTime_.restart();
2578 
2579  emit viewChanged();
2580  }
2581 }
2582 
2583 
2584 
2585 void glViewer::computeProjStereo( int _viewportWidth, int _viewportHeight, Viewer::ViewerProperties& _properties, ACG::GLMatrixd* _outLeft, ACG::GLMatrixd* _outRight )
2586 {
2587  double l, r, t, b, w, h, a, radians, wd2, ndfl, zerop, xrange;
2588 
2589  w = double(_viewportWidth);
2590  h = double(_viewportHeight);
2591  a = w / h;
2592 
2593  double fovy = OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble();
2594  radians = fovy * 0.5 / 180.0 * M_PI;
2595  wd2 = _properties.nearPlane() * tan(radians);
2596  zerop = _properties.nearPlane() + ((_properties.farPlane() - _properties.nearPlane()) * OpenFlipperSettings().value("Core/Stereo/FocalDistance", 0.5).toDouble() );
2597  ndfl = _properties.nearPlane() / zerop ;
2598  xrange = a * wd2 * 2 * zerop / _properties.nearPlane();
2599 
2600  l = -a*wd2;
2601  r = a*wd2;
2602  t = wd2;
2603  b = -wd2;
2604 
2605  double offset = 0.5 * OpenFlipperSettings().value("Core/Stereo/EyeDistance", 0.07).toDouble() * xrange;
2606  double offset2 = offset * ndfl;
2607 
2608  if (_outLeft)
2609  {
2610  _outLeft->identity();
2611  _outLeft->frustum(l+offset2, r+offset2, b, t, _properties.nearPlane(), _properties.farPlane());
2612  _outLeft->translate(offset, 0.0, 0.0);
2613  }
2614 
2615  if (_outRight)
2616  {
2617  _outRight->identity();
2618  _outRight->frustum(l-offset2, r-offset2, b, t, _properties.nearPlane(), _properties.farPlane());
2619  _outRight->translate(-offset, 0.0, 0.0);
2620  }
2621 }
2622 
2623 
2624 //=============================================================================
2625 //=============================================================================
2626 
bool cursorPositionValid()
Flag if stereo should be enabled for the current viewer.
virtual void setView(const ACG::GLMatrixd &_modelview, const ACG::GLMatrixd &_inverse_modelview)
set view, used for synchronizing
void releaseGLArea()
undo grabbing GLArea
void set_bounding_box(ACG::Vec3d _min, ACG::Vec3d _max)
Definition: GLState.cc:806
virtual void toggleNavigationMode()
toggle navigation mode
void frustum(Scalar left, Scalar right, Scalar bottom, Scalar top, Scalar near_plane, Scalar far_plane)
multiply self with a perspective projection matrix
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
double nearPlane()
Return distance to near Plane.
void addWheelX(QGraphicsWidget *_item)
Add Wheel Widget to Layout.
virtual void perspectiveProjection()
set perspective view (projectionMode(PERSPECTIVE_PROJECTION))
void signalMouseEventIdentify(QMouseEvent *)
void viewMouseEvent(QMouseEvent *_event)
specialized viewer: hande mouse events
void actionCopyView(const QSize &_windowSize=QSize(-1,-1), const int _splitterWidth=-1, const bool _make_c_string=false)
Vec3d right() const
get right-vector w.r.t. camera coordinates
Definition: GLState.cc:918
void grabGLArea()
get all Mouse & Key Events for GlWidget
QMouseEvent clickEvent_
mouse interaction position
void signalMouseEventLight(QMouseEvent *)
const GLMatrixd & inverse_modelview() const
get inverse modelview matrix
Definition: GLState.hh:811
static double clip(double _angle)
Definition: QtWheel.cc:436
double sceneRadius()
Get radius of the current scene.
ACG::Vec3d cursorPoint3D()
Flag if stereo should be enabled for the current viewer.
void setPlanes(double _near, double _far)
Set near and far plane at the same time.
ACG::Vec3d trackballCenter()
Get virtual trackball center (rotation center when using mouse)
void moveBack()
First person navigation: Move back.
virtual void home()
go to home pos
void slotAnimation()
mouse interaction position
float startDepth_
mouse interaction depth
void viewUpdated()
This signal is emitted when the scene is repainted due to any event.
pick any of the prior targets (should be implemented for all nodes)
Definition: PickTarget.hh:84
bool fast_pick(const QPoint &_mousePos, ACG::Vec3d &_hitPoint)
double lastRotationAngle_
mouse interaction position
void setProjectionMode(const ProjectionMode _mode)
set mode to either ORTHOGRAPHIC_PROJECTION or PERSPECTIVE_PROJECTION
static GLuint getFramebufferRead()
get current read framebuffer of a target
Definition: GLState.cc:2082
QFramebufferObject * mouseCache_
Framebuffer object that holds the pick cache.
virtual void setHome()
set home position
QStringList collectObjectComments(bool visibleOnly, bool targetedOnly)
void push_modelview_matrix()
push modelview matrix
Definition: GLState.cc:1010
void setViewerID(int _viewerID)
Set currently active viewer id.
Definition: IRenderer.cc:1519
void slotClickTimeout()
Handle click timeout.
virtual QSize sizeHint() const
reimplemented
Definition: QtWheel.cc:425
void unLockUpdate()
Unlock display locked by updateLock().
void updateCursorPosition(QPointF _scenePos)
will be called from CursorPainter to inform the viewer that the cursor position changed ...
double ortho_width() const
Get width of the gl scene in orthogonal projection mode.
void setCursor(const QCursor &_cursor)
Sets the current used cursor.
void set_twosided_lighting(bool _b)
set whether transparent or solid objects should be drawn
Definition: GLState.cc:822
void actionPasteView(QSize *_windowSize=NULL, int *_splitterWidth=NULL)
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *_event)
handle mouse double click events
NavigationMode navigationMode() const
get current navigation mode
ACG::Vec3d constrainedRotationAxis_
mouse interaction position
const GLMatrixd & projection() const
get projection matrix
Definition: GLState.hh:786
ProjectionMode
projection mode
void reset_modelview()
reset modelview matrix (load identity)
Definition: GLState.cc:370
void twoSidedLighting(bool _state)
set 2-sided lighting on/off
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:138
virtual void mousePressEvent(QGraphicsSceneMouseEvent *_event)
handle mouse press events
virtual void orthographicProjection()
set orthographic view (projectionMode(ORTHOGRAPHIC_PROJECTION))
QOpenGLFramebufferObject QFramebufferObject
Framebuffer object that holds the pick cache.
virtual void resizeEvent(QGraphicsSceneResizeEvent *_e)
handle resize events
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *_event)
handle mouse move events
QPoint glMapToGlobal(const QPoint &_pos) const
map glarea coords to global coords
bool allowConstrainedRotation()
mouse interaction position
void translate(double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
translate by (_x, _y, _z)
Definition: GLState.cc:533
QSize glSize() const
get size of QGLWIdget
void applyProperties()
int viewport_width() const
get viewport width
Definition: GLState.hh:822
void lookAt(const ACG::Vec3d &_eye, const ACG::Vec3d &_center, const ACG::Vec3d &_up)
Set look at transformation directly.
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.
static GLuint getFramebufferDraw()
get current draw framebuffer of a target
Definition: GLState.cc:2074
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
double wheelZoomFactor()
Zoom factor when using mouse wheel.
void updateProjectionMatrix(double _aspect=0.0)
updates projection matrix
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *_event)
handle mouse release events
void encodeView(QString &_view, const QSize &_windowSize=QSize(-1,-1), const int _toolBarWidth=-1, const bool _make_c_string=false)
void rotate(const ACG::Vec3d &axis, double angle)
rotate the scene (around its center) and update modelview matrix
bool allowRotation_
mouse interaction position
bool updatePickCache_
Should the pick cache be updated.
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)
static double deg(double _angle)
maps _angle from radiants to degrees (works also for clip()ped angles)
Definition: QtWheel.cc:440
QTimer * timer_
mouse interaction position
void animation(bool _state)
set 2-sided lighting on/off
void signalMouseEventClick(QMouseEvent *, bool _double)
void signalMakeActive()
make this widget active
void clearBuffers()
clear buffers viewport rectangle
Definition: GLState.cc:266
static void blendFuncSeparate(GLenum _srcRGB, GLenum _dstRGB, GLenum _srcAlpha, GLenum _dstAlpha)
replaces glBlendFuncSeparate, supports locking
Definition: GLState.cc:1621
void push_projection_matrix()
push projection matrix
Definition: GLState.cc:971
virtual void setFOVY(double _fovy)
Set fovy.
void snapshotFileType(const QString &_type)
static void bindFramebuffer(GLenum _target, GLuint _framebuffer)
replaces glBindFramebuffer, supports locking
Definition: GLState.cc:2089
double aspect_ratio() const
Returns the viewer&#39;s aspect ratio.
ACG::GLState * glstate_
Gl State.
virtual void paintGL(double _aspect=0.0)
draw the scene. Triggered by updateGL().
void multisampling(bool _state)
set multisampling on/off
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
Definition: GLState.hh:307
bool mapToSphere(const QPoint &_p, ACG::Vec3d &_result) const
virtual trackball: map 2D screen point to unit sphere
void initModelviewMatrix()
initialize modelview matrix to identity
static void unlockBlendFuncSeparate()
unlock blend func
Definition: GLState.hh:330
void perspective(double _fovY, double _aspect, double _near_plane, double _far_plane)
perspective projection
Definition: GLState.cc:448
virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *_e)
handle mouse press events
virtual void wheelEvent(QGraphicsSceneWheelEvent *_event)
handle mouse wheel events
double trackballRadius()
Get trackball radius (rotation sphere when using mouse)
const QStringList ALL_OBJECTS
Iterable object range.
ACG::Vec3d sceneCenter()
Get current scene center (rendering center)
void handleNormalNavigation(QMouseEvent *_event)
Navigate through scene if normal mode has been selected.
QTime clickTime_
mouse interaction position
void setScenePos(const ACG::Vec3d &_center, double _radius, const bool _resetTrackBall=false)
QPoint lastPoint2D_
mouse interaction position
void signalMouseEvent(QMouseEvent *, const std::string &)
ACG::Vec3d lastRotationAxis_
mouse interaction position
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
Definition: GLState.cc:1507
void set_max_render_passes(const unsigned int _max)
set maximum number of render passes
Definition: GLState.hh:996
void ortho(double _left, double _right, double _bottom, double _top, double _near_plane, double _far_plane)
orthographic projection
Definition: GLState.cc:402
void analyzeSceneGraph(ACG::SceneGraph::BaseNode *_root, unsigned int &_maxPasses, ACG::Vec3d &_bbmin, ACG::Vec3d &_bbmax)
Analyze the SceneGraph <ACG/Scenegraph/SceneGraphAnalysis.hh>
Vec3d up() const
get up-vector w.r.t. camera coordinates
Definition: GLState.cc:906
void signalWheelEvent(QWheelEvent *, const std::string &)
Emitted in Pick mode. Uses pick mode.
Viewer::ViewerProperties * properties()
Returns a pointer to the Viewer Status.
double fovyModifier_
mouse interaction position
virtual bool blendForStencilRefBit(GLuint _refbit, GLenum &_src, GLenum &_dst, ACG::Vec4f &_color)
static void drawBuffer(GLenum _mode)
replaces glDrawBuffer, supports locking
Definition: GLState.cc:2033
void handleFirstPersonNavigation(QMouseEvent *_event)
Navigate through scene if first person mode has been selected.
QPoint glMapFromGlobal(const QPoint &_pos) const
map global to glarea coords
void resolveStereoAnyglyph(int _viewerID)
Resolve stereo buffers as anaglyph.
void paintCursor(ACG::GLState *_state)
Cursor painting function. The _state has to be setup that 0,0,0 is at the cursor position.
Vec3d unproject(const Vec3d &_winPoint) const
unproject point in window coordinates _winPoint to world coordinates
Definition: GLState.cc:651
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition: GLState.cc:640
ACG::Vec4f backgroundColor()
Get current background color.
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:121
Viewer::ViewerProperties & properties_
All properties for this viewer.
unsigned int glHeight() const
get height of QGLWidget
ProjectionMode projectionMode() const
get current projection mode
void set_clear_color(const Vec4f &_col)
set background color
Definition: GLState.cc:662
virtual void updateGL()
Redraw scene. Triggers paint event for updating the view (cf. drawNow()).
int viewport_height() const
get viewport height
Definition: GLState.hh:824
void get_viewport(int &_left, int &_bottom, int &_width, int &_height) const
get viewport
Definition: GLState.hh:816
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
Definition: GLState.cc:1729
void sceneGraph(ACG::SceneGraph::BaseNode *_root, unsigned int _maxPasses, ACG::Vec3d _bbmin, ACG::Vec3d _bbmax, const bool _resetTrackBall=false)
RendererInfo * active(int _id)
Get the current active renderer.
use provided normals as is
ChildIter find(BaseNode *_node)
Definition: BaseNode.hh:346
void objectMarker(ViewObjectMarker *_marker)
set object marker for viewer
STL namespace.
Interface to add additional rendering functions from within plugins.
bool initialized_
Have the viewer gl properties been initalized.
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 setCoreProfileMode(bool _enable)
Tell renderer to use core or compatibility profile.
Definition: IRenderer.hh:483
virtual void moveEvent(QGraphicsSceneMoveEvent *_e)
handle move events
void snapshotCounter(const int _counter)
Vec3d viewing_direction() const
get viewing ray
Definition: GLState.hh:848
void stereo(bool _stereo)
Flag if stereo should be enabled for the current viewer.
int setupScene(int _viewerID, int _width, int _height, int _samples=0, int _stereoEye=-1)
Bind fbo for scene rendering.
QTime lastMoveTime_
mouse interaction position
virtual bool blendForStencilRefNumber(GLuint _reference, GLenum &_src, GLenum &_dst, ACG::Vec4f &_color)
void viewingDirection(const ACG::Vec3d &_dir, const ACG::Vec3d &_up)
set the viewing direction
double farPlane()
Return distance to far Plane.
QRectF cursorBoundingBox()
Bounding box of the cursor.
Vec3d eye() const
get eye point
Definition: GLState.cc:886
bool backFaceCulling()
Get current state of backface culling.
static void lockBlendFuncSeparate(bool _rgb=true, bool _alpha=true)
lock blend func
Definition: GLState.hh:328
virtual bool stencilRefForObject(BaseObjectData *_obj, GLuint &_reference)=0
void reset_projection()
reset projection matrix (load identity)
Definition: GLState.cc:334
void viewChanged()
This signal is emitted whenever the view is changed by the user.
void show()
Show node: set status to Active.
Definition: BaseNode.hh:407
virtual ~glViewer()
Destructor.
void startDragEvent(QMouseEvent *_event)
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:791
bool wheelInvert()
Invert mouse wheel direction?
virtual void slotWheelY(double _dAngle)
process signals from wheelX_
int numActive(int _id)
Get the number of active post processors for viewer.
QTimer clickTimer_
mouse interaction position
NavigationMode
Navigation mode.
void drawMode(ACG::SceneGraph::DrawModes::DrawMode _mode)
set draw mode (No test if this mode is available!)
void signalCustomContextMenuRequested(const QPoint &)
Viewer::ActionMode actionMode()
get the action mode
virtual void dropEvent(QGraphicsSceneDragDropEvent *_e)
drag & drop for modelview copying
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
CursorPainter * cursorPainter()
Flag if stereo should be enabled for the current viewer.
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
DLLEXPORT ObjectIterator objectsEnd()
Return Iterator to Object End.
static void activeTexture(GLenum _texunit)
replaces glActiveTexture, no locking support
Definition: GLState.cc:1857
virtual void makeCurrent()
Makes this widget the current widget for OpenGL operations.
void traverse_multipass(BaseNode *_node, Action &_action, const unsigned int &_pass)
Definition: SceneGraph.hh:254
void pop_modelview_matrix()
pop modelview matrix
Definition: GLState.cc:1026
void identity()
setup an identity matrix
void pop_projection_matrix()
pop projection matrix
Definition: GLState.cc:989
virtual void slotWheelX(double _dAngle)
process signals from wheelX_
ACG::Vec3d unproject(const ACG::Vec3d &pt)
Framebuffer object that holds the pick cache.
static void bindBuffer(GLenum _target, GLuint _buffer)
replaces glBindBuffer, supports locking
Definition: GLState.cc:1820
void drawCursor()
draw the cursor
double wheelZoomFactorShift()
Zoom factor when using mouse wheel and pressing shift.
virtual void slotWheelZ(double _dist)
process signals from wheelZ_
void hide()
Hide Node: set status to HideNode.
Definition: BaseNode.hh:405
void setglState(ACG::GLState *_glState)
Pointer to the glState of the Viewer.
bool visible()
Is node visible (status == Active)?
Definition: BaseNode.hh:409
void initialize()
initialize all state variables (called by constructor)
Definition: GLState.cc:162
virtual void dragEnterEvent(QGraphicsSceneDragDropEvent *_e)
drag & drop for modelview copying
void setCursorPainter(CursorPainter *_cursorPainter)
sets the current cursor painter
void set_modelview(const GLMatrixd &_m)
set modelview
Definition: GLState.hh:728
unsigned int glWidth() const
get width of QGLWidget
void allow_multisampling(bool _b)
Disable multisampling globally.
Definition: GLState.hh:1051
virtual void snapshot(int _width=0, int _height=0, bool _alpha=false, bool _hideCoordsys=false, int samples=1)
bool enabled()
Returns true if cursor painting is enabled and compatible cursor is set.
virtual void flyTo(const QPoint &_pos, bool _moveBack)
Animated flight to or away from a given point.
bool pick(ACG::SceneGraph::PickTarget _pickTarget, const QPoint &_mousePos, size_t &_nodeIdx, size_t &_targetIdx, ACG::Vec3d *_hitPointPtr=0)
unsigned int activeId(int _id)
Get the id of the active renderer.
void setState()
set the whole stored gl state
Definition: GLState.cc:209
void set_msSinceLastRedraw(unsigned int _ms)
set time passed since last redraw in milliseconds
Definition: GLState.hh:241
double near_plane() const
Returns a chili cheese burger.
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.
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
Definition: GLState.cc:1527
const DataType DATA_ALL(UINT_MAX)
Identifier for all available objects.
void trackMouse(bool _track)
Enable/disable mouse tracking (move events with no button press)
NormalsMode
Automatically normalize normals?
bool lastPoint_hitSphere_
mouse interaction position
virtual void render(ACG::GLState *_glState, Viewer::ViewerProperties &_properties)
rendering function
double orthoWidth()
Get width of the gl scene in orthogonal projection mode (defaults to 2.0)
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)
void moveForward()
First person navigation: Move forward.
void lookAt(const Vec3d &_eye, const Vec3d &_center, const Vec3d &_up)
set camera by lookAt
Definition: GLState.cc:515
Mark per returned reference bits.
glViewer(QGraphicsScene *_scene, OFGLWidget *_glWidget, Viewer::ViewerProperties &_properties, QGraphicsWidget *_parent=0)
double far_plane() const
Returns a peanut butter sandwich.
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
void set_projection(const GLMatrixd &_m)
set projection
Definition: GLState.hh:691
virtual void initializeGL()
Return a resonable size hint.
void signalSceneGraphChanged(ACG::SceneGraph::BaseNode *_root)
scene graph has changed
PostProcessing * postproc_
Post-Processing executor.
void setCoordSysProjection(glViewer::ProjectionMode _mode)
helper function for setting the projection mode of the coordinate system node
ACG::Vec3d lastPoint3D_
mouse interaction position
void translate(const ACG::Vec3d &trans)
translate the scene and update modelview matrix
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
void slotPropertiesUpdated()
std::string pickMode()
get active pick mode
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)
virtual void toggleProjectionMode()
toggle projection mode
int viewerId()
Get the id of the viewer this viewerproperties belongs to.
void strafeLeft()
First person navigation: Strafe left.
virtual void viewAll()
view the whole scene
void viewWheelEvent(QWheelEvent *_event)
specialized viewer: handle wheel events
static void bindTexture(GLenum _target, GLuint _buffer)
replaces glBindTexture, supports locking
Definition: GLState.cc:1868
NormalsMode normalsMode() const
get treatment of normals
void strafeRight()
First person navigation: Strafe Right.