QtBaseViewer.cc

00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                              OpenFlipper                                  *
00004  *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openflipper.org                             *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------*
00008  *  This file is part of OpenFlipper.                                        *
00009  *                                                                           *
00010  *  OpenFlipper is free software: you can redistribute it and/or modify      *
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenFlipper is distributed in the hope that it will be useful,           *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenFlipper. If not,                                  *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/
00034 
00035 /*===========================================================================*\
00036  *                                                                           *
00037  *   $Revision: 7507 $                                                         *
00038  *   $Author: moebius $                                                      *
00039  *   $Date: 2009-10-23 08:27:46 +0200 (Fr, 23. Okt 2009) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 
00044 
00045 
00046 //=============================================================================
00047 //
00048 //  CLASS glViewer - IMPLEMENTATION
00049 //
00050 //=============================================================================
00051 
00052 
00053 //== INCLUDES =================================================================
00054 
00055 #include "QtBaseViewer.hh"
00056 #include "QtGLViewerLayout.hh"
00057 #include "CursorPainter.hh"
00058 #include <ACG/QtWidgets/QtWheel.hh>
00059 #include <ACG/Scenegraph/DrawModes.hh>
00060 #include <ACG/GL/gl.hh>
00061 
00062 #include <iostream>
00063 #include <string>
00064 #include <assert.h>
00065 
00066 #include <QMimeData>
00067 #include <QToolButton>
00068 #include <QFrame>
00069 
00070 #include <QClipboard>
00071 #include <QApplication>
00072 #include <QSplitter>
00073 #include <QLayout>
00074 #include <QPushButton>
00075 #include <QLabel>
00076 #include <QImage>
00077 #include <QColorDialog>
00078 #include <QFileDialog>
00079 #include <QToolTip>
00080 #include <QTextStream>
00081 #include <QDateTime>
00082 #include <QTimer>
00083 
00084 #include <QDesktopWidget>
00085 #include <QMouseEvent>
00086 #include <QVBoxLayout>
00087 #include <QKeyEvent>
00088 #include <QGridLayout>
00089 #include <QContextMenuEvent>
00090 #include <QWheelEvent>
00091 #include <QDropEvent>
00092 #include <QPixmap>
00093 #include <QMenu>
00094 #include <QVariant>
00095 #include <QButtonGroup>
00096 #include <QToolBar>
00097 
00098 #include <QGraphicsView>
00099 #include <QGraphicsScene>
00100 #include <QGraphicsWidget>
00101 #include <QGraphicsGridLayout>
00102 #include <QGraphicsProxyWidget>
00103 #include <QPainter>
00104 #include <QPaintEngine>
00105 
00106 #ifdef max
00107 #  undef max
00108 #endif
00109 
00110 #ifdef min
00111 #  undef min
00112 #endif
00113 
00114 #include <OpenFlipper/BasePlugin/PluginFunctions.hh>
00115 #include <OpenFlipper/common/ViewObjectMarker.hh>
00116 
00117 #include <OpenFlipper/common/GlobalOptions.hh>
00118 
00119 #include <QGLFramebufferObject>
00120 
00121 //== NAMESPACES ===============================================================
00122 
00123 
00124 
00125 //== IMPLEMENTATION ==========================================================
00126 
00127 static const char          VIEW_MAGIC[] =
00128   "ACG::QtWidgets::QGLViewerWidget encoded view";
00129 
00130 //== IMPLEMENTATION ==========================================================
00131 
00132 
00133 glViewer::glViewer( QGraphicsScene* _scene,
00134                     QGLWidget* _glWidget,
00135                     Viewer::ViewerProperties& _properties,
00136                     QGraphicsWidget* _parent) :
00137   QGraphicsWidget(_parent),
00138   glareaGrabbed_(false),
00139   projectionUpdateLocked_(false),
00140   blending_(true),
00141   glScene_(_scene),
00142   glWidget_(_glWidget),
00143   cursorPainter_(0),
00144   cursorPositionValid_(false),
00145   pickCache_(0),
00146   updatePickCache_(true),
00147   pickCacheSupported_(true),
00148   clickEvent_(QEvent::MouseButtonPress, QPoint (), Qt::NoButton, Qt::NoButton, Qt::NoModifier),
00149   properties_(_properties),
00150   glstate_(0),
00151   initialized_(false)
00152 {
00153 
00154   // widget stuff
00155   createWidgets();
00156 
00157   // bind GL context to GL state class
00158   glstate_ = new ACG::GLState();
00159   properties_.setglState( glstate_ );
00160 
00161   // state
00162   orthoWidth_       = 2.0;
00163   isRotating_       = false;
00164   lookAround_       = false;
00165   near_             = 0.1;
00166   far_              = 100.0;
00167   fovy_             = 45.0;
00168 
00169   sceneGraphRoot_   = 0;
00170 
00171   normalsMode_      = NORMALIZE_NORMALS;
00172   projectionMode_   = PERSPECTIVE_PROJECTION;
00173   navigationMode_   = NORMAL_NAVIGATION;
00174 
00175 
00176   light_matrix_.identity();
00177 
00178   trackMouse_ = false;
00179 
00180   // stereo
00181   stereo_ = false;
00182 
00183   // Note: we start locked (initialization of updateLocked_)
00184   // will be unlocked in initializeGL()
00185 
00186   QSizePolicy sp = sizePolicy();
00187   sp.setHorizontalPolicy( QSizePolicy::Expanding );
00188   sp.setVerticalPolicy( QSizePolicy::Expanding );
00189   sp.setHorizontalStretch( 1 );
00190   sp.setVerticalStretch( 1 );
00191   setSizePolicy( sp );
00192 
00193   redrawTime_.start ();
00194 
00195   // timer for animation
00196   timer_ = new QTimer( this );
00197   connect( timer_, SIGNAL(timeout()), this, SLOT( slotAnimation()) );
00198 
00199   allowRotation_ = true;
00200 
00201 
00202   connect( &properties_,SIGNAL(updated()), this, SLOT( slotPropertiesUpdated() ) );
00203 
00204 
00205   //check for updated properties once
00206   slotPropertiesUpdated();
00207 
00208   setAcceptDrops(true);
00209 
00210   setHome();
00211 
00212   // initialize custom anaglyph stereo
00213   agTexWidth_ = 0;
00214   agTexHeight_ = 0;
00215   agTexture_[0] = 0;
00216   agTexture_[1] = 0;
00217   agProgram_ = 0;
00218   customAnaglyphSupported_ = false;
00219 
00220   clickTimer_.setSingleShot (true);
00221   connect (&clickTimer_, SIGNAL(timeout ()), this, SLOT(slotClickTimeout ()));
00222 }
00223 
00224 
00225 //-----------------------------------------------------------------------------
00226 
00227 
00228 glViewer::~glViewer()
00229 {
00230   finiCustomAnaglyphStereo ();
00231   delete glstate_;
00232 }
00233 
00234 
00235 //-----------------------------------------------------------------------------
00236 
00237 
00238 QSize
00239 glViewer::sizeHint() const
00240 {
00241   return QSize( 600, 600 );
00242 }
00243 
00244 //-----------------------------------------------------------------------------
00245 
00246 
00247 void glViewer::makeCurrent() {
00248   glWidget_->makeCurrent();
00249 }
00250 
00251 void glViewer::swapBuffers() {
00252   glWidget_->swapBuffers();
00253 }
00254 
00255 
00256 //-----------------------------------------------------------------------------
00257 
00258 
00259 void glViewer::sceneGraph(ACG::SceneGraph::BaseNode* _root, const bool _resetTrackBall)
00260 {
00261   sceneGraphRoot_ = _root;
00262 
00263   if (sceneGraphRoot_ )
00264   {
00265     // get scene size
00266     ACG::SceneGraph::BoundingBoxAction act;
00267     ACG::SceneGraph::traverse(sceneGraphRoot_, act);
00268 
00269     ACG::Vec3d bbmin = (ACG::Vec3d) act.bbMin();
00270     ACG::Vec3d bbmax = (ACG::Vec3d) act.bbMax();
00271 
00272     if ( ( bbmin[0] > bbmax[0] ) ||
00273          ( bbmin[1] > bbmax[1] ) ||
00274          ( bbmin[2] > bbmax[2] )   )
00275       setScenePos( ACG::Vec3d( 0.0,0.0,0.0 ) , 1.0, _resetTrackBall );
00276     else
00277       setScenePos( ( bbmin + bbmax )        * 0.5,
00278                    ( bbmax - bbmin ).norm() * 0.5,
00279                    _resetTrackBall);
00280   }
00281 
00282   updateGL();
00283 
00284   emit(signalSceneGraphChanged(sceneGraphRoot_));
00285 }
00286 
00287 
00288 //-----------------------------------------------------------------------------
00289 
00290 
00291 void glViewer::trackMouse(bool _track)
00292 {
00293   trackMouse_ = _track;
00294 }
00295 
00296 
00297 //-----------------------------------------------------------------------------
00298 
00299 void glViewer::perspectiveProjection()
00300 {
00301   projectionMode(PERSPECTIVE_PROJECTION);
00302   updateGL();
00303 }
00304 
00305 
00306 void glViewer::orthographicProjection()
00307 {
00308   projectionMode(ORTHOGRAPHIC_PROJECTION);
00309   updateGL();
00310 }
00311 
00312 
00313 void glViewer::toggleProjectionMode()
00314 {
00315   if (projectionMode_ == ORTHOGRAPHIC_PROJECTION)
00316     projectionMode(PERSPECTIVE_PROJECTION);
00317   else
00318     projectionMode(ORTHOGRAPHIC_PROJECTION);
00319 
00320   updateGL();
00321 }
00322 
00323 
00324 void glViewer::projectionMode(ProjectionMode _p)
00325 {
00326   if ((projectionMode_ = _p) == ORTHOGRAPHIC_PROJECTION)
00327     emit projectionModeChanged( true );
00328   else
00329     emit projectionModeChanged( false );
00330 
00331   updateProjectionMatrix();
00332 
00333   emit viewChanged();
00334 }
00335 
00336 void glViewer::toggleNavigationMode()
00337 {
00338   if (navigationMode_ == NORMAL_NAVIGATION)
00339     navigationMode(FIRSTPERSON_NAVIGATION);
00340   else
00341     navigationMode(NORMAL_NAVIGATION);
00342 }
00343 
00344 
00345 void glViewer::navigationMode(NavigationMode _n)
00346 {
00347   if ((navigationMode_ = _n) == NORMAL_NAVIGATION)
00348     emit navigationModeChanged( true );
00349   else
00350     emit navigationModeChanged( false );
00351 }
00352 
00353 
00354 void glViewer::updateProjectionMatrix()
00355 {
00356   if( projectionUpdateLocked_ )
00357     return;
00358 
00359   makeCurrent();
00360 
00361   glstate_->reset_projection();
00362 
00363   // In scereo mode we have to use a perspective matrix
00364   if (stereo_ || projectionMode_ == PERSPECTIVE_PROJECTION)
00365   {
00366     double aspect;
00367 
00368     if (isVisible() && glWidth() && glHeight())
00369       aspect = (double) glWidth() / (double) glHeight();
00370     else
00371       aspect = 1.0;
00372 
00373     glstate_->perspective(fovy_, (GLdouble) aspect,
00374                           near_, far_);
00375   }
00376   else
00377   {
00378     double aspect;
00379 
00380     if (isVisible() && glWidth() && glHeight())
00381       aspect = (double) glWidth() / (double) glHeight();
00382     else
00383       aspect = 1.0;
00384 
00385     glstate_->ortho( -orthoWidth_, orthoWidth_,
00386                      -orthoWidth_/aspect, orthoWidth_/aspect,
00387                      near_, far_ );
00388   }
00389 
00390 }
00391 
00392 
00393 //-----------------------------------------------------------------------------
00394 
00395 
00396 void glViewer::setScenePos(const ACG::Vec3d& _center, double _radius, const bool _resetTrackBall)
00397 {
00398   if(_resetTrackBall) {
00399     trackball_center_ = _center;
00400   }
00401 
00402   scene_center_ = _center;
00403 
00404   scene_radius_ = trackball_radius_ = _radius;
00405 
00406   ACG::Vec3d c = glstate_->modelview().transform_point(scene_center_);
00407 
00408   // Set far plane
00409   far_    = std::max(0.0002f * scene_radius_,  -(c[2] - scene_radius_));
00410 
00411   // Set near plane
00412   near_   = std::max(0.0001f * scene_radius_,  -(c[2] + scene_radius_));
00413 
00414 
00415   updateProjectionMatrix();
00416   updateGL();
00417 
00418   emit viewChanged();
00419 }
00420 
00421 //-----------------------------------------------------------------------------
00422 
00423 void glViewer::setSceneCenter( const ACG::Vec3d& _center ) {
00424 
00425         scene_center_ = _center;
00426 }
00427 
00428 //-----------------------------------------------------------------------------
00429 
00430 void glViewer::setTrackBallCenter( const ACG::Vec3d& _center ) {
00431   
00432   trackball_center_ = _center;
00433 }
00434 
00435 //----------------------------------------------------------------------------
00436 
00437 
00438 void glViewer::viewingDirection( const ACG::Vec3d& _dir, const ACG::Vec3d& _up )
00439 {
00440   // calc eye point for this direction
00441   ACG::Vec3d eye = scene_center_ - _dir*(3.0*scene_radius_);
00442 
00443   glstate_->reset_modelview();
00444   glstate_->lookAt((ACG::Vec3d)eye, (ACG::Vec3d)scene_center_, (ACG::Vec3d)_up);
00445 
00446   emit viewChanged();
00447 }
00448 
00449 
00450 //-----------------------------------------------------------------------------
00451 
00452 
00453 void glViewer::normalsMode(NormalsMode _mode)
00454 {
00455   makeCurrent();
00456 
00457   switch(normalsMode_ = _mode)
00458   {
00459     case DONT_TOUCH_NORMALS:
00460       glDisable(GL_NORMALIZE);
00461       break;
00462 
00463     case NORMALIZE_NORMALS:
00464       glEnable(GL_NORMALIZE);
00465       break;
00466   }
00467 
00468   updateGL();
00469 }
00470 
00471 
00472 //-----------------------------------------------------------------------------
00473 
00474 
00475 void
00476 glViewer::copyToImage( QImage& _image,
00477                        unsigned int _l, unsigned int _t,
00478                        unsigned int _w, unsigned int _h,
00479                            GLenum /* _buffer */ )
00480 {
00481 
00482 //    qApp->processEvents();
00483 //    makeCurrent();
00484 
00485   _image = glWidget_->grabFrameBuffer(true).copy (_l, _t, _w, _h).convertToFormat (QImage::Format_RGB32);
00486 }
00487 
00488 
00489 //-----------------------------------------------------------------------------
00490 
00491 
00492 void glViewer::updateGL()
00493 {
00494   if (!properties_.updateLocked() && isVisible() )
00495   {
00496     updatePickCache_ = true;
00497     update();
00498 
00499     emit viewUpdated();
00500   }
00501 }
00502 
00503 
00504 
00505 //-----------------------------------------------------------------------------
00506 
00507 
00508 void glViewer::drawScene()
00509 {
00510   QTime  timer;
00511   timer.start();
00512 
00513 
00514   // *****************************************************************
00515   // Adjust clipping planes
00516   // *****************************************************************
00517   // Far plane
00518   ACG::Vec3d c = glstate_->modelview().transform_point(scene_center_);
00519 
00520   // Set far plane
00521   far_    = std::max(0.0002f * scene_radius_,  -(c[2] - scene_radius_));
00522 
00523   // Set near plane
00524   near_   = std::max(0.0001f * scene_radius_,  -(c[2] + scene_radius_));
00525 
00526   // measure distance from scene center ( as projection onto the z-Axis )
00527 //   if ( -c[2] < scene_radius_ ) {
00528 //     std::cerr << "Camera in scene radius" << std::endl;
00529 //
00530 //   }
00531 //
00532 //   std::cerr << "-c[2]   : " << -c[2] << std::endl;
00533 //   std::cerr << "radius  : " << scene_radius_ << std::endl;
00534 //   std::cerr << "z-range : " << far_ - near_ << std::endl;
00535 //   std::cerr << "Near    : " << near_ << std::endl;
00536 //   std::cerr << "Far     : " << far_ << std::endl;
00537 //   near_   = std::max(far_ / 256.0f,  -(c[2] + scene_radius_));
00538 
00539   updateProjectionMatrix();
00540 
00541   // store time since last repaint in gl state and restart timer
00542   glstate_->set_msSinceLastRedraw (redrawTime_.restart ());
00543 
00544   // draw mono or stereo
00545   makeCurrent();
00546   if (stereo_) drawScene_stereo();
00547   else         drawScene_mono();
00548 
00549   glFinish();
00550   frame_time_ = timer.elapsed();
00551 
00552 
00553 }
00554 
00555 
00556 //-----------------------------------------------------------------------------
00557 
00558 
00559 void glViewer::drawScene_mono()
00560 {
00561   if (sceneGraphRoot_)
00562   {
00563     if (! properties_.renderPicking() ) {
00564 
00565       ViewObjectMarker *oM = properties_.objectMarker();
00566       GLuint refBits = 0;
00567       QSet<GLuint> references;
00568 
00569       if (oM)
00570       {
00571         glClear (GL_STENCIL_BUFFER_BIT);
00572         glEnable (GL_STENCIL_TEST);
00573         glStencilOp (GL_KEEP, GL_KEEP, GL_ZERO);
00574         glStencilFunc (GL_ALWAYS, 0, ~0);
00575 
00576         for (PluginFunctions::ObjectIterator o_it(PluginFunctions::ALL_OBJECTS, DATA_ALL) ;
00577                                              o_it != PluginFunctions::objectsEnd(); ++o_it)
00578         {
00579           bool ok;
00580           GLuint ref;
00581 
00582           ok = oM->stencilRefForObject(*o_it, ref);
00583 
00584           if (ok)
00585           {
00586             o_it->stencilRefNode ()->setReference (ref);
00587             o_it->stencilRefNode ()->show ();
00588             refBits |= ref;
00589             references << ref;
00590           }
00591           else
00592             o_it->stencilRefNode ()->hide ();
00593         }
00594       }
00595 
00596       ACG::SceneGraph::DrawAction action( properties_.drawMode() , false);
00597       ACG::SceneGraph::traverse(sceneGraphRoot_, action, *glstate_, properties_.drawMode() );
00598 
00599       if( blending_ )
00600       {
00601         ACG::SceneGraph::DrawAction action(properties_.drawMode(), true);
00602         ACG::SceneGraph::traverse(sceneGraphRoot_, action, *glstate_, properties_.drawMode());
00603       }
00604 
00605       if (oM)
00606       {
00607         if (oM->type() == ViewObjectMarker::PerBit)
00608         {
00609           references.clear ();
00610           for (unsigned int i = 0; i < sizeof (GLuint) * 8; i++)
00611             if (refBits & (1 << i))
00612               references << (1 << i);
00613         }
00614 
00615         glPushAttrib(GL_ALL_ATTRIB_BITS);
00616 
00617         glEnable(GL_BLEND);
00618         glDisable(GL_DEPTH_TEST);
00619         glDisable(GL_LIGHTING);
00620         glDisable(GL_DITHER);
00621 
00622         int vp_l, vp_b, vp_w, vp_h;
00623         glstate_->get_viewport (vp_l, vp_b, vp_w, vp_h);
00624 
00625         glMatrixMode(GL_PROJECTION);
00626         glPushMatrix ();
00627         glLoadIdentity();
00628         glOrtho(0, vp_w, vp_h, 0, 0, 1.0);
00629         glMatrixMode(GL_MODELVIEW);
00630         glPushMatrix ();
00631         glLoadIdentity();
00632 
00633         glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
00634 
00635         foreach (unsigned int ref, references)
00636         {
00637           bool ok;
00638           GLenum sfactor;
00639           GLenum dfactor;
00640           ACG::Vec4f color;
00641           unsigned int mask = ~0;
00642 
00643           if (oM->type() == ViewObjectMarker::PerBit)
00644           {
00645             ok = oM->blendForStencilRefBit (ref, sfactor, dfactor, color);
00646             mask = ref;
00647           }
00648           else
00649             ok = oM->blendForStencilRefNumber (ref, sfactor, dfactor, color);
00650 
00651           if (!ok)
00652             continue;
00653 
00654           glStencilFunc (GL_EQUAL, ref, mask);
00655 
00656           glBlendFunc (sfactor, dfactor);
00657           glColor4f (color[0], color [1], color [2], color[3]);
00658 
00659           glBegin (GL_QUADS);
00660           glVertex2i(0, 0);
00661           glVertex2i(0, vp_h);
00662           glVertex2i(vp_w, vp_h);
00663           glVertex2i(vp_w, 0);
00664           glEnd ();
00665 
00666         }
00667 
00668         glMatrixMode(GL_PROJECTION);
00669         glPopMatrix ();
00670         glMatrixMode(GL_MODELVIEW);
00671         glPopMatrix ();
00672 
00673         glPopAttrib ();
00674         glDisable (GL_STENCIL_TEST);
00675       }
00676     } else {
00677 
00678       // prepare GL state
00679       makeCurrent();
00680 
00681       glDisable(GL_LIGHTING);
00682       glDisable(GL_BLEND);
00683       glClear(GL_DEPTH_BUFFER_BIT);
00684       glInitNames();
00685       glPushName((GLuint) 0);
00686 
00687       // do the picking
00688       glstate_->pick_init (true);
00689       ACG::SceneGraph::PickAction action(*glstate_, properties_.renderPickingMode(), properties_.drawMode());
00690       ACG::SceneGraph::traverse(sceneGraphRoot_, action);
00691 
00692       glEnable(GL_LIGHTING);
00693       glEnable(GL_BLEND);
00694     }
00695   }
00696 
00697   if (cursorPainter_ && cursorPainter_->enabled () && cursorPositionValid_)
00698   {
00699     glstate_->push_modelview_matrix ();
00700     // reset view transformation
00701     glstate_->reset_modelview ();
00702     // translate cursor position to 0,0
00703     glstate_->translate (cursorPoint3D_[0], cursorPoint3D_[1], cursorPoint3D_[2]);
00704     // paint cursor
00705     cursorPainter_->paintCursor (glstate_);
00706     glstate_->pop_modelview_matrix ();
00707   }
00708 
00709   draw_lights();
00710 }
00711 
00712 
00713 //-----------------------------------------------------------------------------
00714 
00715 
00716 void
00717 glViewer::drawScene_stereo()
00718 {
00719   if (OpenFlipper::Options::stereoMode () == OpenFlipper::Options::OpenGL && OpenFlipper::Options::glStereo ())
00720   {
00721     drawScene_glStereo ();
00722     return;
00723   }
00724   else if (OpenFlipper::Options::stereoMode () == OpenFlipper::Options::AnaglyphCustom && customAnaglyphSupported_)
00725   {
00726     drawScene_customAnaglyphStereo ();
00727 
00728     // if somthing went wrong, fallback to normal anaglyph
00729     if (customAnaglyphSupported_)
00730       return;
00731   } else if (OpenFlipper::Options::stereoMode () == OpenFlipper::Options::Philips )
00732   {
00733     drawScenePhilipsStereo ();
00734     
00735     return;
00736     
00737   }
00738   
00739   
00740 
00741   drawScene_anaglyphStereo ();
00742 }
00743 
00744 
00745 //-----------------------------------------------------------------------------
00746 
00747 
00748 void glViewer::setHome()
00749 {
00750   home_modelview_          = glstate_->modelview();
00751   home_inverse_modelview_  = glstate_->inverse_modelview();
00752   homeOrthoWidth_          = orthoWidth_;
00753   home_center_             = trackball_center_;
00754   home_radius_             = trackball_radius_;
00755 }
00756 
00757 
00758 void glViewer::home()
00759 {
00760   makeCurrent();
00761   glstate_->set_modelview(home_modelview_, home_inverse_modelview_);
00762   orthoWidth_ = homeOrthoWidth_;
00763   trackball_center_ = home_center_;
00764   trackball_radius_ = home_radius_;
00765   updateProjectionMatrix();
00766   updateGL();
00767 
00768   emit viewChanged();
00769 
00770 }
00771 
00772 
00773 //-----------------------------------------------------------------------------
00774 
00775 
00776 void glViewer::viewAll()
00777 {
00778         makeCurrent();
00779 
00780         // update scene graph (get new bounding box and set projection right, including near and far plane)
00781         properties_.lockUpdate();
00782 
00783         // move center (in camera coords) to origin and translate in -z dir
00784         translate(-(glstate_->modelview().transform_point(scene_center_))
00785                         - ACG::Vec3d(0.0, 0.0, 3.0 * scene_radius_));
00786 
00787         orthoWidth_ = 1.1 * scene_radius_;
00788         double aspect = (double) glWidth() / (double) glHeight();
00789         if (aspect > 1.0)
00790                 orthoWidth_ *= aspect;
00791 
00792         sceneGraph(PluginFunctions::getSceneGraphRootNode(), true);
00793 
00794         properties_.unLockUpdate();
00795         updateProjectionMatrix();
00796         updateGL();
00797 
00798     emit viewChanged();
00799 
00800 }
00801 
00802 
00803 //-----------------------------------------------------------------------------
00804 
00805 
00806 void glViewer::flyTo(const QPoint& _pos, bool _move_back)
00807 {
00808   makeCurrent();
00809 
00810   unsigned int nodeIdx, targetIdx;
00811   ACG::Vec3d hitPoint;
00812 
00813   if (pick( ACG::SceneGraph::PICK_ANYTHING, _pos, nodeIdx, targetIdx, &hitPoint))
00814   {
00815     if (projectionMode_ == PERSPECTIVE_PROJECTION)
00816     {
00817       ACG::Vec3d eye(glstate_->eye());
00818       ACG::Vec3d t = hitPoint - eye;
00819       ACG::Vec3d e = eye + t * (_move_back ? -0.5f : 0.5f);
00820       flyTo(e, hitPoint, 300);
00821     }
00822     else
00823     {
00824       // Zoom in or out?
00825       orthoWidth_ *= _move_back ? 2.0 : 0.5;
00826 
00827       // Set the double click point as the new trackball center
00828       // Rotations will use this point as the center.
00829       trackball_center_ = hitPoint;
00830 
00832 
00833       // Update the projection matrix
00834       updateProjectionMatrix();
00835 
00836       // Redraw scene
00837       updateGL();
00838 
00839       emit viewChanged();
00840     }
00841 
00842 
00843   }
00844 }
00845 
00846 
00847 void glViewer::flyTo(const ACG::Vec3d&  _position,
00848                          const ACG::Vec3d&  _center,
00849                          double        _time)
00850 {
00851   makeCurrent();
00852 
00853   // compute rotation
00854   ACG::Vec3d c = glstate_->modelview().transform_point(_center);
00855   ACG::Vec3d p = glstate_->modelview().transform_point(_position);
00856   ACG::Vec3d view =(p-c).normalize();
00857   ACG::Vec3d z(0,0,1);
00858   ACG::Vec3d axis = (z % -view).normalize();
00859   double angle = acos(std::max(-1.0,
00860                               std::min(1.0,
00861                                        (z | view)))) / M_PI * 180.0;
00862 
00863   if (angle > 175)
00864     axis  = ACG::Vec3d(0,1,0);
00865 
00866 
00867   // compute translation
00868   ACG::Vec3d target = glstate_->modelview().transform_point(_center);
00869   ACG::Vec3d trans ( -target[0],
00870                 -target[1],
00871                 -target[2] - (_position-_center).norm() );
00872 
00873 
00874 
00875   // how many frames in _time ms ?
00876   unsigned int  frames = (unsigned int)(_time / frame_time_);
00877   if (frames > 1000) frames=1000;
00878 
00879 
00880 
00881 
00882   // animate it
00883   if (frames > 10)
00884   {
00885     ACG::Vec3d t = trans / (double)frames;
00886     double a = angle / (double)frames;
00887 
00888     for (unsigned int i=0; i<frames; ++i)
00889     {
00890       translate(t);
00891       if (fabs(a) > FLT_MIN)
00892              rotate(axis, a, _center);
00893 
00894       update();
00895       qApp->processEvents();
00896     }
00897     updatePickCache_ = true;
00898   }
00899 
00900 
00901   // no animation
00902   else
00903   {
00904     translate(trans);
00905     if (fabs(angle) > FLT_MIN)
00906       rotate(axis, angle, _center);
00907 
00908     updateGL();
00909   }
00910 
00911 
00912   trackball_center_ = _center;
00913   trackball_radius_ = std::max(scene_radius_,
00914                                (_center-_position).norm()*0.9f);
00915 }
00916 
00917 
00918 //-----------------------------------------------------------------------------
00919 
00920 
00921 void glViewer::setView(const ACG::GLMatrixd& _modelview,
00922                                           const ACG::GLMatrixd& _inverse_modelview)
00923 {
00924   makeCurrent();
00925   glstate_->set_modelview(_modelview, _inverse_modelview);
00926   updateGL();
00927 
00928   emit viewChanged();
00929 }
00930 
00931 
00932 //-----------------------------------------------------------------------------
00933 
00934 
00935 void glViewer::initializeGL()
00936 {
00937 
00938   // lock update
00939   properties_.lockUpdate();
00940 
00941   // init GL state
00942   glstate_->initialize();
00943 
00944   // OpenGL state
00945   glEnable(GL_DEPTH_TEST);
00946   glEnable(GL_LIGHTING);
00947   glDisable(GL_DITHER);
00948   glShadeModel( GL_FLAT );
00949 
00950 
00951   projectionMode(   projectionMode_   );
00952   normalsMode(      normalsMode_      );
00953 
00954   // Update all settings which would require a redraw
00955   applyProperties();
00956 
00957   // light sources
00958   light_matrix_.identity();
00959   update_lights();
00960 
00961 
00962   // scene pos and size
00963   scene_center_ = trackball_center_ = ACG::Vec3d( 0.0, 0.0, 0.0 );
00964   scene_radius_ = trackball_radius_ = 1.0;
00965   orthoWidth_   = 2.0;
00966 
00967 
00968   // modelview
00969   glstate_->translate(0.0, 0.0, -3.0);
00970   setHome();
00971 
00972 
00973   // pixel transfer
00974   glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
00975   glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
00976   glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
00977   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00978   glPixelStorei(GL_PACK_ROW_LENGTH, 0);
00979   glPixelStorei(GL_PACK_SKIP_ROWS, 0);
00980   glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
00981   glPixelStorei(GL_PACK_ALIGNMENT, 1);
00982 
00983 
00984   // unlock update (we started locked)
00985   properties_.unLockUpdate();
00986 
00987   customAnaglyphSupported_ = glewIsSupported("GL_ARB_fragment_program") &&
00988       (glewIsSupported("GL_ARB_texture_rectangle") ||
00989        glewIsSupported("GL_EXT_texture_rectangle") ||
00990        glewIsSupported("GL_NV_texture_rectangle"));
00991 
00992   initialized_ = true;
00993 
00994   if (sceneGraphRoot_)
00995   {
00996     sceneGraph(sceneGraphRoot_, true);
00997     viewAll ();
00998   }
00999 }
01000 
01001 
01002 //-----------------------------------------------------------------------------
01003 
01007 void  glViewer::draw_lights() {
01008 //   makeCurrent();
01009 // //
01010 //   glMatrixMode(GL_MODELVIEW);
01011 //   glPushMatrix();
01012 //   glLoadIdentity();
01013 //   glMultMatrixd(light_matrix_.data());
01014 //
01015 //   std::cerr << "light_matrix_\n" << light_matrix_ << std::endl;
01016 // //
01017 //   glPointSize(3);
01018 // //
01019 //   glColor3f(1.0,1.0,1.0);
01020 // //   glDisable(GL_LIGHTING);
01021 // //   glDisable(GL_BLEND);
01022 //   glBegin(GL_LINES);
01023 //     glVertex3f(0.0,  0.0, -1000.0);
01024 //     glVertex3f(0.0,  0.0, 10000.0);
01025 //     glVertex3f(0.0, -1000.0,0.0);
01026 //     glVertex3f(0.0, 1000.0,0.0);
01027 //     glVertex3f(1000.0,0.0,0.0);
01028 //     glVertex3f(-1000.0,0.0,0.0);
01029 // //     glVertex3d(0.0,  0.0, 1.1);
01030 // //     glVertex3d(-1.0,  1.0, 0.8);
01031 // //     glVertex3d( 1.0,  1.0, 0.8);
01032 //
01033 //   glEnd();
01034 // //   glEnable(GL_LIGHTING);
01035 // //   glEnable(GL_BLEND);
01036 // //
01037 //   glPopMatrix();
01038 
01039 }
01040 
01041 void glViewer::update_lights()
01042 {
01043   makeCurrent();
01044 
01045   glMatrixMode(GL_MODELVIEW);
01046   glPushMatrix();
01047   glLoadIdentity();
01048   glMultMatrixd(light_matrix_.data());
01049 
01050   GLfloat pos[4], col[4];
01051 
01052   col[0] = col[1] = col[2] = 0.7;
01053   pos[3] = col[3] = 0.0;
01054 
01055 #define SET_LIGHT(i,x,y,z) {                    \
01056     pos[0]=x; pos[1]=y; pos[2]=z;               \
01057     glLightfv(GL_LIGHT##i, GL_POSITION, pos);   \
01058     glLightfv(GL_LIGHT##i, GL_DIFFUSE,  col);   \
01059     glLightfv(GL_LIGHT##i, GL_SPECULAR, col);   \
01060     glEnable(GL_LIGHT##i);                      \
01061   }
01062 
01063   SET_LIGHT(0,  0.0,  0.0, 1.0);
01064   SET_LIGHT(1, -1.0,  1.0, 0.7);
01065   SET_LIGHT(2,  1.0,  1.0, 0.7);
01066 
01067   col[0] = col[1] = col[2] = 0.3; col[3] = 1.0;
01068   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
01069 
01070   glPopMatrix();
01071 }
01072 
01073 
01074 void glViewer::rotate_lights(ACG::Vec3d& _axis, double _angle)
01075 {
01076   light_matrix_.rotate(_angle, _axis[0], _axis[1], _axis[2], ACG::MULT_FROM_LEFT);
01077   update_lights();
01078 }
01079 
01080 
01081 //-----------------------------------------------------------------------------
01082 
01083 
01084 void glViewer::paintGL()
01085 {
01086   if (!initialized_)
01087     initializeGL ();
01088 
01089   if (!properties_.updateLocked())
01090   {
01091     ACG::Vec4f clear_color;
01092 
01093     properties_.lockUpdate();
01094 
01095     glPushAttrib (GL_ALL_ATTRIB_BITS);
01096 
01097     glEnable(GL_DEPTH_TEST);
01098     glEnable(GL_LIGHTING);
01099     glDisable(GL_DITHER);
01100     glShadeModel( GL_FLAT );
01101 
01102     glMatrixMode(GL_PROJECTION);
01103     glPushMatrix();
01104 
01105     glMatrixMode(GL_MODELVIEW);
01106     glPushMatrix();
01107 
01108 
01109     normalsMode(      normalsMode_      );
01110 
01111     applyProperties();
01112 
01113     // light sources
01114     update_lights();
01115 
01116     glstate_->setState ();
01117 
01118     glColor4f(1.0,0.0,0.0,1.0);
01119 
01120     if (properties_.renderPicking())
01121     {
01122       clear_color = properties_.glState().clear_color();
01123       properties_.glState().set_clear_color (ACG::Vec4f (0.0, 0.0, 0.0, 1.0));
01124     }
01125 
01126     // clear (stereo mode clears buffers on its own)
01127     if (!stereo_)
01128       glstate_->clearBuffers ();
01129 
01130     properties_.unLockUpdate();
01131 
01132     // draw scene
01133     drawScene();
01134 
01135     glPopMatrix();
01136 
01137     glMatrixMode(GL_PROJECTION);
01138     glPopMatrix();
01139 
01140     glPopAttrib ();
01141 
01142     if (properties_.renderPicking())
01143       properties_.glState().set_clear_color (clear_color);
01144   }
01145 }
01146 
01147 
01148 //-----------------------------------------------------------------------------
01149 
01150 
01151 void glViewer::resizeEvent(QGraphicsSceneResizeEvent *)
01152 {
01153   updateProjectionMatrix();
01154   glstate_->viewport(scenePos().x(),
01155                      scene()->height () - scenePos().y() - size().height (),
01156                      size().width (), size().height (),
01157                      scene()->width (), scene()->height ());
01158   update();
01159 
01160   emit viewChanged();
01161 }
01162 
01163 void glViewer::moveEvent (QGraphicsSceneMoveEvent *)
01164 {
01165   glstate_->viewport(scenePos().x(),
01166                      scene()->height () - scenePos().y() - size().height (),
01167                      size().width (), size().height (),
01168                      scene()->width (), scene()->height ());
01169   update();
01170 
01171   emit viewChanged();
01172 }
01173 
01174 //-----------------------------------------------------------------------------
01175 
01176 void glViewer::encodeView(QString& _view)
01177 {
01178   // Get current matrices
01179   const ACG::GLMatrixd m = glstate_->modelview();
01180   const ACG::GLMatrixd p = glstate_->projection();
01181 
01182   // Add modelview matrix to output
01183   _view += QString(VIEW_MAGIC) + "\n";
01184   _view += QString::number(m(0,0)) + " " + QString::number(m(0,1)) + " " + QString::number(m(0,2)) + " " + QString::number(m(0,3)) + "\n";
01185   _view += QString::number(m(1,0)) + " " + QString::number(m(1,1)) + " " + QString::number(m(1,2)) + " " + QString::number(m(1,3)) + "\n";
01186   _view += QString::number(m(2,0)) + " " + QString::number(m(2,1)) + " " + QString::number(m(2,2)) + " " + QString::number(m(2,3)) + "\n";
01187   _view += QString::number(m(3,0)) + " " + QString::number(m(3,1)) + " " + QString::number(m(3,2)) + " " + QString::number(m(3,3)) + "\n";
01188 
01189   // Add projection matrix to output
01190   _view += QString::number(p(0,0)) + " " + QString::number(p(0,1)) + " " + QString::number(p(0,2)) + " " + QString::number(p(0,3)) + "\n";
01191   _view += QString::number(p(1,0)) + " " + QString::number(p(1,1)) + " " + QString::number(p(1,2)) + " " + QString::number(p(1,3)) + "\n";
01192   _view += QString::number(p(2,0)) + " " + QString::number(p(2,1)) + " " + QString::number(p(2,2)) + " " + QString::number(p(2,3)) + "\n";
01193   _view += QString::number(p(3,0)) + " " + QString::number(p(3,1)) + " " + QString::number(p(3,2)) + " " + QString::number(p(3,3)) + "\n";
01194 
01195   // add gl width/height, current projection Mode and the ortho mode width to output
01196   _view += QString::number(glWidth()) + " " +  QString::number(glHeight()) + " " + QString::number(projectionMode_) + " " + QString::number(orthoWidth_) + "\n";
01197 }
01198 
01199 
01200 //----------------------------------------------------------------------------
01201 
01202 
01203 bool glViewer::decodeView(const QString& _view)
01204 {
01205   if (_view.left(sizeof(VIEW_MAGIC)-1) != QString(VIEW_MAGIC))
01206     return false;
01207 
01208   // Remove the magic from the string
01209   QString temp = _view;
01210   temp.remove(0,sizeof(VIEW_MAGIC));
01211 
01212   //Split it into its components
01213   QStringList split = temp.split(QRegExp("[\\n\\s]"),QString::SkipEmptyParts);
01214 
01215   ACG::GLMatrixd m, p;
01216   int            w, h, pMode;
01217 
01218   // Check if the number of components matches the expected size
01219   if ( split.size() != 36 ) {
01220     std::cerr << "Unable to paste view ... wrong parameter count!! is" <<  split.size()  << std::endl;
01221     return false;
01222   }
01223 
01224   // Parse the components
01225   bool ok = true;;
01226 
01227   m(0,0) = split[0].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01228   m(0,1) = split[1].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01229   m(0,2) = split[2].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01230   m(0,3) = split[3].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01231   m(1,0) = split[4].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01232   m(1,1) = split[5].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01233   m(1,2) = split[6].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01234   m(1,3) = split[7].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01235   m(2,0) = split[8].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01236   m(2,1) = split[9].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01237   m(2,2) = split[10].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01238   m(2,3) = split[11].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01239   m(3,0) = split[12].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01240   m(3,1) = split[13].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01241   m(3,2) = split[14].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01242   m(3,3) = split[15].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01243   p(0,0) = split[16].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01244   p(0,1) = split[17].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01245   p(0,2) = split[18].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01246   p(0,3) = split[19].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01247   p(1,0) = split[20].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01248   p(1,1) = split[21].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01249   p(1,2) = split[22].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01250   p(1,3) = split[23].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01251   p(2,0) = split[24].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01252   p(2,1) = split[25].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01253   p(2,2) = split[26].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01254   p(2,3) = split[27].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01255   p(3,0) = split[28].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01256   p(3,1) = split[29].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01257   p(3,2) = split[30].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01258   p(3,3) = split[31].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01259 
01260   w =  split[32].toInt(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01261   h =  split[33].toInt(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01262   pMode =  split[34].toInt(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01263   orthoWidth_ = split[35].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01264 
01265   // Switch to our gl context
01266   makeCurrent();
01267 
01268   // set projection mode
01269   if (projectionMode_ != (ProjectionMode)pMode)
01270     projectionMode((ProjectionMode)pMode);
01271 
01272   // Apply new modelview matrix
01273   glstate_->set_modelview(m);
01274 
01275 
01276   std::cerr << "Todo : Add Checkbox if size should also be pasted" << std::endl;
01277 
01278 //   if (w>0 && h>0 &&
01279 //       action_["PasteDropSize"]->isChecked() )
01280 //   {
01281 //     glstate_->set_projection(p);
01282 //     glView_->setFixedSize(w,h);
01283 //     updateGeometry();
01284 //   }
01285 
01286   updateGL();
01287 
01288   return true;
01289 }
01290 
01291 
01292 //-----------------------------------------------------------------------------
01293 
01294 
01295 void glViewer::actionCopyView()
01296 {
01297   QString view; encodeView(view);
01298   QApplication::clipboard()->setText(view);
01299 }
01300 
01301 
01302 //-----------------------------------------------------------------------------
01303 
01304 
01305 void glViewer::actionPasteView()
01306 {
01307   QString view; view=QApplication::clipboard()->text();
01308   decodeView(view);
01309 }
01310 
01311 
01312 //-----------------------------------------------------------------------------
01313 
01314 void
01315 glViewer::createWidgets()
01316 {
01317   // Construct GL context & widget
01318 
01319   wheelZ_=new ACG::QtWidgets::QtWheel( 0,"wheel-z",ACG::QtWidgets::QtWheel::Vertical);
01320   wheelZ_->setMinimumSize(wheelZ_->sizeHint());
01321   wheelZ_->setMaximumSize(wheelZ_->sizeHint());
01322   connect(wheelZ_,SIGNAL(angleChangedBy(double)),
01323           this,SLOT(slotWheelZ(double)));
01324   wheelZ_->setToolTip( tr("Translate along <b>z-axis</b>."));
01325   wheelZ_->setWhatsThis( tr("Translate along <b>z-axis</b>."));
01326 
01327   wheelY_=new ACG::QtWidgets::QtWheel( 0,"wheel-y",ACG::QtWidgets::QtWheel::Horizontal);
01328   wheelY_->setMinimumSize(wheelY_->sizeHint());
01329   wheelY_->setMaximumSize(wheelY_->sizeHint());
01330   connect(wheelY_,SIGNAL(angleChangedBy(double)),
01331           this,SLOT(slotWheelY(double)));
01332   wheelY_->setToolTip(tr("Rotate around <b>y-axis</b>."));
01333   wheelY_->setWhatsThis( tr("Rotate around <b>y-axis</b>."));
01334 
01335   wheelX_=new ACG::QtWidgets::QtWheel( 0,"wheel-x" ,ACG::QtWidgets::QtWheel::Vertical);
01336   wheelX_->setMinimumSize(wheelX_->sizeHint());
01337   wheelX_->setMaximumSize(wheelX_->sizeHint());
01338   connect(wheelX_,SIGNAL(angleChangedBy(double)),
01339           this,SLOT(slotWheelX(double)));
01340   wheelX_->setToolTip(tr("Rotate around <b>x-axis</b>."));
01341   wheelX_->setWhatsThis( tr("Rotate around <b>x-axis</b>."));
01342 
01343   // Hide or show wheels (depending on ini option)
01344   if(!OpenFlipper::Options::showWheelsAtStartup()) {
01345 
01346           slotHideWheels();
01347   }
01348 
01349   QGraphicsWidget *wheelX = glScene_->addWidget (wheelX_);
01350   QGraphicsWidget *wheelY = glScene_->addWidget (wheelY_);
01351   QGraphicsWidget *wheelZ = glScene_->addWidget (wheelZ_);
01352 
01353   wheelX_->setWindowOpacity (0.5);
01354   wheelY_->setWindowOpacity (0.5);
01355   wheelZ_->setWindowOpacity (0.5);
01356 
01357   wheelX->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
01358   wheelY->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
01359   wheelZ->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
01360 
01361   glBaseLayout_ = new QtGLViewerLayout;
01362   glBaseLayout_->addWheelX(wheelX);
01363   glBaseLayout_->addWheelY(wheelY);
01364   glBaseLayout_->addWheelZ(wheelZ);
01365 
01366   connect(wheelX_,SIGNAL(hideWheel()),this,SLOT(slotHideWheels()));
01367   connect(wheelY_,SIGNAL(hideWheel()),this,SLOT(slotHideWheels()));
01368   connect(wheelZ_,SIGNAL(hideWheel()),this,SLOT(slotHideWheels()));
01369 
01370   setLayout(glBaseLayout_);
01371 }
01372 
01373 //-----------------------------------------------------------------------------
01374 
01375 
01376 void glViewer::translate(const ACG::Vec3d& _trans)
01377 {
01378   makeCurrent();
01379   glstate_->translate(_trans[0], _trans[1], _trans[2], ACG::MULT_FROM_LEFT);
01380 
01381   emit viewChanged();
01382 }
01383 
01384 
01385 //-----------------------------------------------------------------------------
01386 
01387 
01388 void glViewer::initModelviewMatrix()
01389 {
01390   makeCurrent();
01391   glstate_->reset_modelview();
01392 }
01393 
01394 
01395 //-----------------------------------------------------------------------------
01396 
01397 
01398 void glViewer::rotate(const ACG::Vec3d&  _axis,
01399                           double        _angle,
01400                           const ACG::Vec3d&  _center)
01401 {
01402   makeCurrent();
01403   ACG::Vec3d t = glstate_->modelview().transform_point(_center);
01404   glstate_->translate(-t[0], -t[1], -t[2], ACG::MULT_FROM_LEFT);
01405   glstate_->rotate(_angle, _axis[0], _axis[1], _axis[2], ACG::MULT_FROM_LEFT);
01406   glstate_->translate( t[0],  t[1],  t[2], ACG::MULT_FROM_LEFT);
01407 
01408   emit viewChanged();
01409 }
01410 
01411 
01412 //-----------------------------------------------------------------------------
01413 
01414 
01415 unsigned int glViewer::glWidth() const {
01416   return size().width();
01417 }
01418 unsigned int glViewer::glHeight() const {
01419   return size().height();
01420 }
01421 QSize glViewer::glSize() const {
01422   return QSize(size().width(),size().height());
01423 }
01424 QPoint glViewer::glMapFromGlobal( const QPoint& _pos ) const {
01425   QPoint p (scene()->views().front()->mapFromGlobal(_pos));
01426   QPointF f (mapFromScene(QPointF(p.x(), p.y ())));
01427   return QPoint (f.x(), f.y());
01428 }
01429 
01430 QPoint glViewer::glMapToGlobal( const QPoint& _pos ) const {
01431   QPointF f (mapToScene(QPointF(_pos.x(), _pos.y ())));
01432   QPoint p (f.x(), f.y());
01433   return scene()->views().front()->mapToGlobal(p);
01434 }
01435 
01436 //-----------------------------------------------------------------------------
01437 
01438 
01439 void glViewer::slotWheelX(double _dAngle)
01440 {
01441   rotate(ACG::Vec3d(1,0,0),ACG::QtWidgets::QtWheel::deg(ACG::QtWidgets::QtWheel::clip(_dAngle)));
01442   updateGL();
01443 
01444   emit viewChanged();
01445 }
01446 
01447 void glViewer::slotWheelY(double _dAngle)
01448 {
01449   rotate(ACG::Vec3d(0,1,0),ACG::QtWidgets::QtWheel::deg(ACG::QtWidgets::QtWheel::clip(_dAngle)));
01450   updateGL();
01451 
01452   emit viewChanged();
01453 }
01454 
01455 void glViewer::slotWheelZ(double _dist)
01456 {
01457   double dz=_dist*0.5/M_PI*scene_radius_*2.0;
01458   translate(ACG::Vec3d(0,0,dz));
01459   updateGL();
01460 
01461   emit viewChanged();
01462 }
01463 
01464 //-----------------------------------------------------------------------------
01465 
01466 
01467 void glViewer::grabGLArea()
01468 {
01469   glareaGrabbed_ = true;
01470 
01471   if (cursorPainter_)
01472     cursorPainter_->setCursor(Qt::BlankCursor);
01473   else
01474     setCursor(Qt::BlankCursor);
01475   grabMouse();
01476   grabKeyboard();
01477 }
01478 
01479 void glViewer::releaseGLArea()
01480 {
01481   glareaGrabbed_ = false;
01482 
01483   ungrabMouse();
01484   ungrabKeyboard();
01485 
01486   if (cursorPainter_)
01487     cursorPainter_->setCursor(Qt::ArrowCursor);
01488   else
01489     setCursor(Qt::ArrowCursor);
01490 }
01491 
01492 
01493 //-----------------------------------------------------------------------------
01494 
01495 
01496 void glViewer::contextMenuEvent(QGraphicsSceneContextMenuEvent* _e)
01497 {
01498   QPoint p (_e->pos().x(), _e->pos().y());
01499   emit signalCustomContextMenuRequested (p);
01500 }
01501 
01502 
01503 //-----------------------------------------------------------------------------
01504 
01505 void glViewer::mousePressEvent(QGraphicsSceneMouseEvent* _e)
01506 {
01507   QPoint p (_e->scenePos().x(), _e->scenePos().y());
01508   QMouseEvent me(QEvent::MouseButtonPress ,p, _e->screenPos(), _e->button(),
01509                  _e->buttons(), _e->modifiers());
01510   _e->accept ();
01511 
01512   emit signalMakeActive();
01513   glScene_->update ();
01514 
01515   // right button pressed => popup menu (ignore here)
01516   if (_e->button() != Qt::RightButton )
01517   {
01518     switch (properties_.actionMode())
01519     {
01520       case Viewer::ExamineMode:
01521         if ((_e->modifiers() & Qt::ControlModifier)) // drag&drop
01522           emit startDragEvent( &me );
01523         else
01524           viewMouseEvent(&me); // examine
01525 
01526         if (clickTimer_.isActive ())
01527         {
01528           clickTime_ = QTime ();
01529           clickTimer_.stop ();
01530         }
01531         else
01532         {
01533           clickTime_.start ();
01534           clickEvent_ = me;
01535         }
01536         break;
01537 
01538       case Viewer::LightMode:
01539         lightMouseEvent(&me);
01540         break;
01541 
01542       case Viewer::PickingMode: // give event to application
01543         emit(signalMouseEvent(&me, properties_.pickMode() ));
01544         emit(signalMouseEvent(&me));
01545         break;
01546 
01547       case Viewer::QuestionMode: // give event to application
01548         emit(signalMouseEventIdentify(&me));
01549         break;
01550     }
01551   }
01552 }
01553 
01554 
01555 //-----------------------------------------------------------------------------
01556 
01557 
01558 void glViewer::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* _e)
01559 {
01560   QPoint p (_e->scenePos().x(), _e->scenePos().y());
01561   QMouseEvent me(QEvent::MouseButtonDblClick ,p, _e->screenPos(), _e->button(),
01562                  _e->buttons(), _e->modifiers());
01563   _e->accept ();
01564 
01565   emit signalMakeActive();
01566   glScene_->update ();
01567 
01568   switch (properties_.actionMode())
01569   {
01570     case Viewer::ExamineMode:
01571       viewMouseEvent(&me);
01572       emit signalMouseEventClick (&me, true);
01573       break;
01574 
01575     case Viewer::LightMode:
01576       lightMouseEvent(&me);
01577       break;
01578 
01579     case Viewer::PickingMode: // give event to application
01580       emit(signalMouseEvent(&me, properties_.pickMode() ));
01581       emit(signalMouseEvent(&me));
01582       break;
01583 
01584     case Viewer::QuestionMode: // give event to application
01585       emit(signalMouseEventIdentify(&me));
01586       break;
01587   }
01588 }
01589 
01590 
01591 //-----------------------------------------------------------------------------
01592 
01593 
01594 void glViewer::mouseMoveEvent(QGraphicsSceneMouseEvent* _e)
01595 {
01596   QPoint p (_e->scenePos().x(), _e->scenePos().y());
01597   QMouseEvent me(QEvent::MouseMove ,p, _e->screenPos(), _e->button(),
01598                  _e->buttons(), _e->modifiers());
01599   _e->accept();
01600 
01601   switch ( properties_.actionMode() )
01602   {
01603     case Viewer::ExamineMode:
01604       viewMouseEvent(&me);
01605       break;
01606 
01607     case Viewer::LightMode:
01608       lightMouseEvent(&me);
01609       break;
01610 
01611     case Viewer::PickingMode:
01612       // give event to application
01613       // deliver mouse moves with no button down, if tracking is enabled,
01614       if ((_e->buttons() & (Qt::LeftButton | Qt::MidButton | Qt::RightButton))
01615           || trackMouse_)
01616       {
01617         emit(signalMouseEvent(&me, properties_.pickMode() ));
01618         emit(signalMouseEvent(&me));
01619       }
01620       break;
01621 
01622     case Viewer::QuestionMode: // give event to application
01623       emit(signalMouseEventIdentify(&me));
01624       break;
01625 
01626     default: // avoid warning
01627       break;
01628   }
01629 }
01630 
01631 //-----------------------------------------------------------------------------
01632 
01633 
01634 void glViewer::mouseReleaseEvent(QGraphicsSceneMouseEvent* _e)
01635 {
01636   QPoint p (_e->scenePos().x(), _e->scenePos().y());
01637   QMouseEvent me(QEvent::MouseButtonRelease ,p, _e->screenPos(), _e->button(),
01638                  _e->buttons(), _e->modifiers());
01639   _e->accept();
01640 
01641 //   if (_event->button() == Qt::RightButton )
01642 //     hidePopupMenus();
01643 
01644   if (_e->button() != Qt::RightButton || (properties_.actionMode() == Viewer::PickingMode) )
01645   {
01646     switch ( properties_.actionMode() )
01647     {
01648       case Viewer::ExamineMode:
01649         viewMouseEvent(&me);
01650 
01651         if (!clickTime_.isNull ())
01652         {
01653           int elapsed = clickTime_.elapsed ();
01654           QPoint diff = clickEvent_.pos () - me.pos ();
01655 
01656           if (abs (diff.x ()) <= 1 && abs (diff.y ()) <= 1 && elapsed <= QApplication::doubleClickInterval () / 2)
01657           {
01658             clickTimer_.setSingleShot (true);
01659             clickTimer_.setInterval (QApplication::doubleClickInterval () - elapsed);
01660             clickTimer_.start ();
01661           }
01662           else
01663           {
01664             clickTime_ = QTime ();
01665             clickTimer_.stop ();
01666           }
01667         }
01668         break;
01669 
01670       case Viewer::LightMode:
01671         lightMouseEvent(&me);
01672         break;
01673 
01674       case Viewer::PickingMode: // give event to application
01675         emit(signalMouseEvent(&me, properties_.pickMode() ));
01676         emit(signalMouseEvent(&me));
01677         break;
01678 
01679       case Viewer::QuestionMode: // give event to application
01680         emit(signalMouseEventIdentify(&me));
01681         break;
01682 
01683       default: // avoid warning
01684         break;
01685     }
01686   }
01687 
01688   isRotating_ = false;
01689 }
01690 
01691 
01692 //-----------------------------------------------------------------------------
01693 
01694 
01695 void glViewer::wheelEvent(QGraphicsSceneWheelEvent* _e)
01696 {
01697   QPoint p (_e->scenePos().x(), _e->scenePos().y());
01698   QWheelEvent we(p, _e->screenPos(), _e->delta(), _e->buttons(),
01699                  _e->modifiers(), _e->orientation());
01700   _e->accept();
01701 
01702   switch ( properties_.actionMode() )
01703   {
01704     case Viewer::ExamineMode:
01705       viewWheelEvent(&we);
01706       break;
01707 
01708     case Viewer::PickingMode: // give event to application
01709       emit(signalWheelEvent(&we, properties_.pickMode() ));
01710       break;
01711 
01712     default: // avoid warning
01713       break;
01714   }
01715 
01716   isRotating_ = false;
01717 }
01718 
01719 //-----------------------------------------------------------------------------
01720 
01721 void glViewer::dragEnterEvent(QGraphicsSceneDragDropEvent* _e)
01722 {
01723   std::cerr << "dragEnter" << std::endl;
01724 
01725   QPoint p (_e->pos().x(), _e->pos().y());
01726   QDragEnterEvent de(p, _e->possibleActions(), _e->mimeData(), _e->buttons(),
01727                      _e->modifiers ());
01728   emit dragEnterEvent(&de);
01729   _e->accept();
01730 }
01731 
01732 //-----------------------------------------------------------------------------
01733 
01734 
01735 void glViewer::dropEvent(QGraphicsSceneDragDropEvent* _e)
01736 {
01737   std::cerr << "drop" << std::endl;
01738 
01739   QPoint p (_e->pos().x(), _e->pos().y());
01740   QDropEvent de(p, _e->possibleActions(), _e->mimeData(), _e->buttons(),
01741                 _e->modifiers ());
01742   emit dropEvent(&de);
01743   _e->accept();
01744 }
01745 
01746 //-----------------------------------------------------------------------------
01747 
01748 
01749 void glViewer::viewMouseEvent(QMouseEvent* _event) {
01750 
01751   if (navigationMode_ == NORMAL_NAVIGATION) {
01752 
01753     handleNormalNavigation(_event);
01754 
01755   } else if (navigationMode_ == FIRSTPERSON_NAVIGATION) {
01756 
01757     handleFirstPersonNavigation(_event);
01758   }
01759 
01760 }
01761 
01762 //----------------------------------------------------------------------------
01763 
01764 void glViewer::handleFirstPersonNavigation( QMouseEvent* _event) {
01765 
01766   // Ego-shooter navigation mode is selected
01767   QPointF f(mapFromScene(QPointF(_event->pos().x(), _event->pos().y())));
01768   QPoint pos(f.x(), f.y());
01769 
01770   switch (_event->type()) {
01771 
01772   case QEvent::MouseButtonPress: {
01773     lastPoint2D_ = pos;
01774     lookAround_ = true;
01775     break;
01776   }
01777 
01778   case QEvent::MouseButtonDblClick: {
01779     if (allowRotation_)
01780       flyTo(_event->pos(), _event->button() == Qt::MidButton);
01781     break;
01782   }
01783 
01784   case QEvent::MouseMove: {
01785 
01786     if(!lookAround_) break;
01787 
01788     // Considering center point of screen as origin
01789     QPoint newpos = QPoint(pos.x() - glWidth() / 2, glHeight() / 2 - pos.y());
01790     QPoint oldpos = QPoint(lastPoint2D_.x() - glWidth() / 2, glHeight() / 2 - lastPoint2D_.y());
01791 
01792     double x = 2.0 * newpos.x() / glWidth();
01793     double y = 2.0 * newpos.y() / glHeight();
01794 
01795     double xo = 2.0 * oldpos.x() / glWidth();
01796     double yo = 2.0 * oldpos.y() / glHeight();
01797 
01798     double diffx = xo - x;
01799     double diffy = yo - y;
01800 
01801     ACG::Vec3d yaxis = glstate_->modelview().transform_vector(glstate_->up());
01802     ACG::Vec3d xaxis = glstate_->modelview().transform_vector(glstate_->right());
01803 
01804     rotate(yaxis, -diffx * 90, glstate_->eye());
01805     rotate(xaxis, diffy * 90, glstate_->eye());
01806 
01807     lastPoint2D_ = pos;
01808 
01809     updateGL();
01810     lastMoveTime_.restart();
01811 
01812     emit viewChanged();
01813 
01814     break;
01815   }
01816 
01817   case QEvent::MouseButtonRelease: {
01818     lookAround_ = false;
01819     break;
01820   }
01821 
01822   default: // avoid warning
01823     break;
01824   }
01825 }
01826 
01827 //----------------------------------------------------------------------------
01828 
01829 void glViewer::handleNormalNavigation( QMouseEvent* _event ) {
01830 
01831   // Normal navigation mode is selected
01832   QPointF f(mapFromScene(QPointF(_event->pos().x(), _event->pos().y())));
01833   QPoint pos(f.x(), f.y());
01834 
01835   switch (_event->type()) {
01836 
01837     case QEvent::MouseButtonPress: {
01838         // shift key -> set rotation center
01839         if (_event->modifiers() & Qt::ShiftModifier) {
01840             ACG::Vec3d c;
01841             if (fast_pick(pos, c)) {
01842                 trackball_center_ = c;
01843                 trackball_radius_ = std::max(scene_radius_, (c - glstate_->eye()).norm() * 0.9f);
01844             }
01845         }
01846 
01847         lastPoint_hitSphere_ = mapToSphere(lastPoint2D_ = pos, lastPoint3D_);
01848         isRotating_ = true;
01849         timer_->stop();
01850 
01851         break;
01852     }
01853 
01854     case QEvent::MouseButtonDblClick: {
01855       if (allowRotation_)
01856           flyTo(_event->pos(), _event->button() == Qt::MidButton);
01857       break;
01858     }
01859 
01860     case QEvent::MouseMove: {
01861       double factor = 1.0;
01862 
01863       if (_event->modifiers() == Qt::ShiftModifier)
01864           factor = properties_.wheelZoomFactorShift();
01865 
01866       // mouse button should be pressed
01867       if (_event->buttons() & (Qt::LeftButton | Qt::MidButton)) {
01868         QPoint newPoint2D = pos;
01869 
01870         double value_x, value_y;
01871         ACG::Vec3d newPoint3D;
01872         bool newPoint_hitSphere = mapToSphere(newPoint2D, newPoint3D);
01873 
01874         makeCurrent();
01875 
01876         // move in z direction
01877         if ((_event->buttons() & Qt::LeftButton) && (_event->buttons() & Qt::MidButton)) {
01878           switch (projectionMode()) {
01879             case PERSPECTIVE_PROJECTION: {
01880                 value_y = scene_radius_ * ((newPoint2D.y() - lastPoint2D_.y())) * 3.0 / (double) glHeight();
01881                 translate(ACG::Vec3d(0.0, 0.0, value_y * factor));
01882                 updateGL();
01883                 emit viewChanged();
01884                 break;
01885             }
01886 
01887             case ORTHOGRAPHIC_PROJECTION: {
01888                 value_y = ((newPoint2D.y() - lastPoint2D_.y())) * orthoWidth_ / (double) glHeight();
01889                 orthoWidth_ -= value_y * factor;
01890                 updateProjectionMatrix();
01891                 updateGL();
01892                 emit viewChanged();
01893                 break;
01894             }
01895           }
01896         }
01897 
01898         // move in x,y direction
01899         else if ((_event->buttons() & Qt::MidButton) || (!allowRotation_ && (_event->buttons() & Qt::LeftButton))) {
01900             value_x = scene_radius_ * ((newPoint2D.x() - lastPoint2D_.x())) * 2.0 / (double) glWidth();
01901             value_y = scene_radius_ * ((newPoint2D.y() - lastPoint2D_.y())) * 2.0 / (double) glHeight();
01902             translate(ACG::Vec3d(value_x * factor, -value_y * factor, 0.0));
01903         }
01904 
01905         // rotate
01906         else if (allowRotation_ && (_event->buttons() & Qt::LeftButton)) {
01907             ACG::Vec3d axis(1.0, 0.0, 0.0);
01908             double angle(0.0);
01909 
01910             if (lastPoint_hitSphere_) {
01911 
01912                 if ((newPoint_hitSphere = mapToSphere(newPoint2D, newPoint3D))) {
01913                     axis = lastPoint3D_ % newPoint3D;
01914                     double cos_angle = (lastPoint3D_ | newPoint3D);
01915                     if (fabs(cos_angle) < 1.0) {
01916                         angle = acos(cos_angle) * 180.0 / M_PI * factor;
01917                         angle *= 2.0; // inventor rotation
01918                     }
01919                 }
01920 
01921                 rotate(axis, angle);
01922 
01923             }
01924 
01925             lastRotationAxis_ = axis;
01926             lastRotationAngle_ = angle;
01927         }
01928 
01929         lastPoint2D_ = newPoint2D;
01930         lastPoint3D_ = newPoint3D;
01931         lastPoint_hitSphere_ = newPoint_hitSphere;
01932 
01933         updateGL();
01934         lastMoveTime_.restart();
01935         emit viewChanged();
01936       }
01937       break;
01938     }
01939 
01940     case QEvent::MouseButtonRelease: {
01941       lastPoint_hitSphere_ = false;
01942 
01943       // continue rotation ?
01944       if (isRotating_ && (_event->button() == Qt::LeftButton) && (!(_event->buttons() & Qt::MidButton))
01945               && (lastMoveTime_.elapsed() < 50) && properties_.animation())
01946         timer_->start(0);
01947       break;
01948     }
01949 
01950     default: // avoid warning
01951       break;
01952   }
01953 }
01954 
01955 //-----------------------------------------------------------------------------
01956 
01957 void
01958 glViewer::lightMouseEvent(QMouseEvent* _event)
01959 {
01960   QPointF f (mapFromScene(QPointF(_event->pos().x(), _event->pos().y())));
01961   QPoint pos (f.x(), f.y());
01962 
01963   switch (_event->type())
01964   {
01965     case QEvent::MouseButtonPress:
01966     {
01967       lastPoint_hitSphere_ = mapToSphere( lastPoint2D_= pos,
01968                  lastPoint3D_ );
01969       isRotating_ = true;
01970       timer_->stop();
01971       break;
01972     }
01973 
01974 
01975     case QEvent::MouseMove:
01976     {
01977       // rotate lights
01978       if (_event->buttons() & Qt::LeftButton)
01979       {
01980    QPoint newPoint2D = pos;
01981 
01982    if ( (newPoint2D.x()<0) || (newPoint2D.x() > (int)glWidth()) ||
01983         (newPoint2D.y()<0) || (newPoint2D.y() > (int)glHeight()) )
01984      return;
01985 
01986 
01987    ACG::Vec3d  newPoint3D;
01988    bool   newPoint_hitSphere = mapToSphere( newPoint2D, newPoint3D );
01989 
01990    makeCurrent();
01991 
01992    ACG::Vec3d axis(1.0,0.0,0.0);
01993    double angle(0.0);
01994 
01995    if ( lastPoint_hitSphere_ )
01996    {
01997      if ( ( newPoint_hitSphere = mapToSphere( newPoint2D, newPoint3D ) ) )
01998      {
01999        axis = lastPoint3D_ % newPoint3D;
02000        double cos_angle = ( lastPoint3D_ | newPoint3D );
02001        if ( fabs(cos_angle) < 1.0 ) {
02002          angle = acos( cos_angle ) * 180.0 / M_PI;
02003          angle *= 2.0;
02004        }
02005      }
02006      rotate_lights(axis, angle);
02007    }
02008 
02009    lastPoint2D_ = newPoint2D;
02010    lastPoint3D_ = newPoint3D;
02011    lastPoint_hitSphere_ = newPoint_hitSphere;
02012 
02013    updateGL();
02014       }
02015       break;
02016     }
02017 
02018 
02019     default: // avoid warning
02020       break;
02021   }
02022 }
02023 
02024 //-----------------------------------------------------------------------------
02025 
02026 void glViewer::viewWheelEvent( QWheelEvent* _event)
02027 {
02028   double factor = properties_.wheelZoomFactor();
02029 
02030   if (_event->modifiers() == Qt::ShiftModifier)
02031     factor = properties_.wheelZoomFactorShift();
02032 
02033   if (projectionMode() == PERSPECTIVE_PROJECTION || stereo_)
02034   {
02035     double d = -(double)_event->delta() / 120.0 * 0.2 * factor * trackball_radius_/3;
02036     translate( ACG::Vec3d(0.0, 0.0, d) );
02037     updateGL();
02038   }
02039   else
02040   {
02041     double d = (double)_event->delta() / 120.0 * 0.2 * factor * orthoWidth_;
02042     orthoWidth_ += d;
02043     updateProjectionMatrix();
02044     updateGL();
02045   }
02046 
02047   emit viewChanged();
02048 }
02049 
02050 
02051 //-----------------------------------------------------------------------------
02052 
02053 
02054 bool glViewer::mapToSphere(const QPoint& _v2D, ACG::Vec3d& _v3D) const
02055 {
02056   if ( (_v2D.x() >= 0) && (_v2D.x() < (int)glWidth()) &&
02057        (_v2D.y() >= 0) && (_v2D.y() < (int)glHeight()) )
02058   {
02059     double x   = (double)(_v2D.x() - ((double)glWidth() / 2.0))  / (double)glWidth();
02060     double y   = (double)(((double)glHeight() / 2.0) - _v2D.y()) / (double)glHeight();
02061     double sinx         = sin(M_PI * x * 0.5);
02062     double siny         = sin(M_PI * y * 0.5);
02063     double sinx2siny2   = sinx * sinx + siny * siny;
02064 
02065     _v3D[0] = sinx;
02066     _v3D[1] = siny;
02067     _v3D[2] = sinx2siny2 < 1.0 ? sqrt(1.0 - sinx2siny2) : 0.0;
02068 
02069     return true;
02070   }
02071   else return false;
02072 }
02073 
02074 
02075 //-----------------------------------------------------------------------------
02076 
02077 
02078 void glViewer::slotAnimation()
02079 {
02080   static int msecs=0, count=0;
02081 
02082   makeCurrent();
02083   rotate( lastRotationAxis_, lastRotationAngle_ );
02084   updateGL();
02085 
02086   if (!properties_.updateLocked()) {
02087     msecs += frame_time_;
02088     if (count >= 10 && msecs >= 500) {
02089       char s[100];
02090       sprintf( s, "%.3f fps", (1000.0 * count / (float)msecs) );
02091       emit statusMessage(s,2000);
02092       count = msecs = 0;
02093     }
02094     else
02095       ++count;
02096   }
02097 }
02098 
02099 void glViewer::applyProperties() {
02100 
02101   glstate_->set_twosided_lighting( properties_.twoSidedLighting() );
02102 
02103   glstate_->set_clear_color( properties_.backgroundColor() );
02104 
02105   glstate_->allow_multisampling( properties_.multisampling() );
02106 
02107   if (properties_.isCCWFront() )
02108     glFrontFace( GL_CCW );
02109   else
02110     glFrontFace( GL_CW );
02111 
02112   if ( properties_.backFaceCulling() )
02113     glEnable( GL_CULL_FACE );
02114   else
02115     glDisable( GL_CULL_FACE );
02116 
02117 }
02118 
02119 void glViewer::slotPropertiesUpdated() {
02120   makeCurrent();
02121   applyProperties();
02122   updateGL();
02123 }
02124 
02125 void glViewer::snapshot(QImage& _image, bool _offScreenRendering)
02126 {
02127 
02128   if ( _offScreenRendering ){
02129     QGLFramebufferObject fb( glstate_->context_width(), glstate_->context_height(), QGLFramebufferObject::CombinedDepthStencil);
02130 
02131     if ( fb.isValid() ){
02132 
02133       fb.bind();
02134       qApp->processEvents();
02135       makeCurrent();
02136       glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
02137       paintGL();
02138       glFinish();
02139 
02140       _image = fb.toImage().copy(scenePos().x(), scenePos().y(), glWidth(), glHeight());
02141 
02142       return;
02143     }
02144   }
02145 
02146   makeCurrent();
02147 
02148   qApp->processEvents();
02149   makeCurrent();
02150   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
02151   paintGL();
02152   glFinish();
02153 
02154   copyToImage(_image, scenePos().x(), scenePos().y(), glWidth(), glHeight(), GL_BACK);
02155 }
02156 
02157 void glViewer::snapshot()
02158 {
02159    makeCurrent();
02160 
02161    qApp->processEvents();
02162    makeCurrent();
02163    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
02164    paintGL();
02165    glFinish();
02166 
02167    QImage snapshot;
02168    copyToImage(snapshot, scenePos().x(), scenePos().y(), glWidth(), glHeight(), GL_BACK);
02169 
02170    QFileInfo fi(properties_.snapshotName());
02171 
02172    QString fname = fi.path() + QDir::separator() +fi.baseName() + "." + QString::number(properties_.snapshotCounter()) + ".";
02173 
02174    QString format="png";
02175 
02176    if (fi.completeSuffix() == "ppm")
02177      format="ppmraw";
02178 
02179    fname += format;
02180 
02181    bool rval=snapshot.save(fname,format.toUpper().toLatin1());
02182 
02183 
02184    if (rval)
02185    {
02186      emit statusMessage (QString(tr("snapshot: "))+fname,5000);
02187    }
02188    else
02189    {
02190      emit statusMessage (QString(tr("could not save snapshot to "))+fname);
02191    }
02192 
02193 }
02194 
02195 void glViewer::slotHideWheels() {
02196   if (isVisible())
02197   {
02198     wheelX_->hide();
02199     wheelY_->hide();
02200     wheelZ_->hide();
02201   }
02202   else
02203   {
02204     show ();
02205     wheelX_->hide();
02206     wheelY_->hide();
02207     wheelZ_->hide();
02208     hide ();
02209   }
02210 }
02211 
02212 void glViewer::slotShowWheels() {
02213   if (isVisible())
02214   {
02215     wheelX_->show();
02216     wheelY_->show();
02217     wheelZ_->show();
02218   }
02219   else
02220   {
02221     show ();
02222     wheelX_->show();
02223     wheelY_->show();
02224     wheelZ_->show();
02225     hide ();
02226   }
02227 }
02228 
02229 bool glViewer::wheelsVisible() {
02230   // TODO: Return valid values
02231   return true;
02232 }
02233 
02234 //-----------------------------------------------------------------------------
02235 
02236 void glViewer::slotClickTimeout()
02237 {
02238   emit signalMouseEventClick (&clickEvent_, false);
02239 }
02240 
02241 //-----------------------------------------------------------------------------
02242 
02243 void glViewer::setCursorPainter (CursorPainter *_cursorPainter)
02244 {
02245   cursorPainter_ = _cursorPainter;
02246 }
02247 
02248 //-----------------------------------------------------------------------------
02249 
02250 void glViewer::updateCursorPosition (QPointF _scenePos)
02251 {
02252   if (!initialized_ || !sceneGraphRoot_ || !isVisible ())
02253     return;
02254 
02255   unsigned int nodeIdx, targetIdx;
02256   ACG::Vec3d tmp;
02257 
02258   // ignore cursor if we are outside of our window
02259   if (!mapRectToScene(boundingRect ()).intersects (cursorPainter_->cursorBoundingBox().translated(_scenePos)))
02260   {
02261     cursorPositionValid_ = false;
02262   }
02263   // only do real pick in stereo mode
02264   else if (stereo_ && OpenFlipper::Options::stereoMousePick() &&
02265            pick (ACG::SceneGraph::PICK_ANYTHING, _scenePos.toPoint(), nodeIdx, targetIdx, &tmp))
02266   {
02267     // the point we get back will contain the view transformation and we have to revert it
02268     cursorPoint3D_ = glstate_->modelview ().transform_point (tmp);
02269 
02270     cursorPositionValid_ = true;
02271   }
02272   else
02273   {
02274     glstate_->push_modelview_matrix ();
02275 
02276     // reset modelview to ignore the view transformation
02277     glstate_->reset_modelview ();
02278 
02279     // Project the depth value of the stereo mode zero paralax plane.
02280     // We need to use this depth to to get the cursor exactly on zero paralax plane in stereo mode
02281     double zerop = near_ + ((far_ - near_) * OpenFlipper::Options::focalDistance ());
02282     ACG::Vec3d zerod = glstate_->project (ACG::Vec3d (0.0, 0.0, -zerop));
02283 
02284     // unproject the cursor into the scene
02285     tmp = glstate_->unproject (ACG::Vec3d (_scenePos.x(), scene()->height () - _scenePos.y(), zerod[2]));
02286     cursorPoint3D_ = tmp;
02287     glstate_->pop_modelview_matrix ();
02288     cursorPositionValid_ = true;
02289   }
02290 }
02291 
02292 //-----------------------------------------------------------------------------
02293 
02294 
02295 void glViewer::moveForward() {
02296     if(navigationMode_ ==  FIRSTPERSON_NAVIGATION) {
02297 
02298         ACG::Vec3d dir = glstate_->viewing_direction();
02299 
02300         dir *= -0.1;
02301 
02302         glstate_->translate(dir[0], dir[1], dir[2]);
02303 
02304         updateGL();
02305         lastMoveTime_.restart();
02306 
02307         emit viewChanged();
02308     }
02309 }
02310 
02311 void glViewer::moveBack() {
02312     if(navigationMode_ ==  FIRSTPERSON_NAVIGATION) {
02313         ACG::Vec3d dir = glstate_->viewing_direction();
02314 
02315         dir *= 0.1;
02316 
02317         glstate_->translate(dir[0], dir[1], dir[2]);
02318 
02319         updateGL();
02320         lastMoveTime_.restart();
02321 
02322         emit viewChanged();
02323     }
02324 }
02325 
02326 void glViewer::strafeLeft() {
02327     if(navigationMode_ ==  FIRSTPERSON_NAVIGATION) {
02328         ACG::Vec3d dir = glstate_->right();
02329 
02330         dir *= 0.1;
02331 
02332         glstate_->translate(dir[0], dir[1], dir[2]);
02333 
02334         updateGL();
02335         lastMoveTime_.restart();
02336 
02337         emit viewChanged();
02338     }
02339 }
02340 
02341 void glViewer::strafeRight() {
02342     if(navigationMode_ ==  FIRSTPERSON_NAVIGATION) {
02343         ACG::Vec3d dir = glstate_->right();
02344 
02345         dir *= -0.1;
02346 
02347         glstate_->translate(dir[0], dir[1], dir[2]);
02348 
02349         updateGL();
02350         lastMoveTime_.restart();
02351 
02352         emit viewChanged();
02353     }
02354 }
02355 
02356 //=============================================================================
02357 //=============================================================================
02358 

acg pic Project OpenFlipper, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .