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: 7103 $                                                       *
00038  *   $Author: moebius $                                                      *
00039  *   $Date: 2009-09-17 10:04:53 +0200 (Do, 17. Sep 2009) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 
00044 
00045 //=============================================================================
00046 //
00047 //  CLASS QtBaseViewer - IMPLEMENTATION
00048 //
00049 //=============================================================================
00050 
00051 
00052 //== INCLUDES =================================================================
00053 
00054 #include "QtBaseViewer.hh"
00055 #include "QtGLGraphicsScene.hh"
00056 #include "QtGLGraphicsView.hh"
00057 #include "QtSceneGraphWidget.hh"
00058 #include "QtWheel.hh"
00059 #include "../Scenegraph/DrawModes.hh"
00060 #include "../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 <QStatusBar>
00077 #include <QImage>
00078 #include <QColorDialog>
00079 #include <QFileDialog>
00080 #include <QToolTip>
00081 #include <QTextStream>
00082 #include <QDateTime>
00083 #include <QTimer>
00084 
00085 #include <QDesktopWidget>
00086 #include <QMouseEvent>
00087 #include <QVBoxLayout>
00088 #include <QKeyEvent>
00089 #include <QGridLayout>
00090 #include <QContextMenuEvent>
00091 #include <QWheelEvent>
00092 #include <QDropEvent>
00093 #include <QPixmap>
00094 #include <QMenu>
00095 #include <QVariant>
00096 #include <QButtonGroup>
00097 #include <QToolBar>
00098 
00099 #include <QGraphicsWidget>
00100 #include <QGraphicsGridLayout>
00101 #include <QGraphicsProxyWidget>
00102 
00103 #include "move.xpm"
00104 #include "light.xpm"
00105 #include "info.xpm"
00106 #include "home.xpm"
00107 #include "set_home.xpm"
00108 #include "viewall.xpm"
00109 #include "pick.xpm"
00110 #include "persp.xpm"
00111 #include "ortho.xpm"
00112 #include "scenegraph.xpm"
00113 #include "mono.xpm"
00114 
00115 
00116 #define homeIcon         home_xpm
00117 #define sethomeIcon      set_home_xpm
00118 #define moveIcon         move_xpm
00119 #define lightIcon        light_xpm
00120 #define questionIcon     info_xpm
00121 #define viewallIcon      viewall_xpm
00122 #define pickIcon         pick_xpm
00123 #define perspectiveIcon  persp_xpm
00124 #define orthoIcon        ortho_xpm
00125 #define sceneGraphIcon   scenegraph_xpm
00126 #define monoIcon         mono_xpm
00127 
00128 
00129 #ifdef max
00130 #  undef max
00131 #endif
00132 
00133 #ifdef min
00134 #  undef min
00135 #endif
00136 
00137 
00138 //== NAMESPACES ===============================================================
00139 
00140 namespace ACG {
00141 namespace QtWidgets {
00142 
00143 
00144 //== IMPLEMENTATION ==========================================================
00145 
00146 static const char          VIEW_MAGIC[] =
00147   "ACG::QtWidgets::QGLViewerWidget encoded view";
00148 
00149 //== IMPLEMENTATION ==========================================================
00150 
00151 
00152 QtBaseViewer::QtBaseViewer( QWidget* _parent,
00153                             const char* /* _name */ ,
00154                             QStatusBar *_statusBar,
00155                             const QGLFormat* _format,
00156                             const QtBaseViewer* _share,
00157                             Options _options ) :
00158   QWidget(_parent),
00159   statusbar_(0),
00160   glareaGrabbed_(false),
00161   updateLocked_(false),
00162   projectionUpdateLocked_(false),
00163   blending_(true),
00164   sceneGraphDialog_(0),
00165   options_(_options),
00166   privateStatusBar_(0),
00167   disableKeyHandling_(false),
00168   externalDrag_(false),
00169   snapshotName_("snap.png"),
00170   snapshotCounter_(0),
00171   snapshot_(0),
00172   pick_mode_name_(""),
00173   pick_mode_idx_(-1),
00174   renderPicking_(false),
00175   pickRendererMode_(ACG::SceneGraph::PICK_ANYTHING)
00176 
00177 {
00178   // check for OpenGL support
00179   if ( !QGLFormat::hasOpenGL() )
00180   {
00181     std::cerr << "This system has no OpenGL support.\n";
00182     exit(1);
00183   }
00184 
00185 
00186   // widget stuff
00187   createWidgets(_format,_statusBar,_share);
00188 
00189 
00190   // bind GL context to GL state class
00191   glstate_ = new GLState();
00192 
00193 
00194   // state
00195   orthoWidth_       = 2.0;
00196   isRotating_       = false;
00197   near_             = 0.1;
00198   far_              = 100.0;
00199   fovy_             = 45.0;
00200 
00201   focalDist_        = 3.0;
00202   eyeDist_          = 0.01;
00203 
00204   sceneGraphRoot_   = 0;
00205   curDrawMode_      = SceneGraph::DrawModes::NONE;
00206   availDrawModes_   = SceneGraph::DrawModes::NONE;
00207 
00208   normalsMode_      = DONT_TOUCH_NORMALS;
00209   faceOrientation_  = CCW_ORIENTATION;
00210   projectionMode_   = PERSPECTIVE_PROJECTION;
00211   navigationMode_   = NORMAL_NAVIGATION;
00212   
00213   
00214   backFaceCulling_  = false;
00215   twoSidedLighting_ = true;
00216   animation_        = false;
00217 
00218   light_matrix_.identity();
00219 
00220 
00221   snapshot_=new QImage;
00222 
00223   trackMouse_ = false;
00224   popupEnabled_ = true;
00225 
00226 
00227   // stereo
00228   stereo_ = false;
00229 
00230 
00231   pickMenu_ = 0;
00232   funcMenu_ = 0;
00233   drawMenu_ = 0;
00234 
00235 
00236   // init action modes: Examine & Pick
00237   actionMode_ = PickingMode;
00238   lastActionMode_ = PickingMode;
00239   examineMode();
00240 
00241 
00242   // clipboard sync stuff
00243   synchronized_ = false;
00244   skipNextSync_ = false;
00245 
00246   socket_ = new QUdpSocket();
00247 
00248   for (int i=6666; i<6676; ++i)
00249     if ( socket_->bind( i ) )
00250     {
00251       std::cout << "listen on port " << i << "\n";
00252       break;
00253     }
00254 
00255   add_sync_host("127.0.0.1");
00256 
00257 
00258 
00259   // Note: we start locked (initialization of updateLocked_)
00260   // will be unlocked in initializeGL()
00261 
00262 
00263   // Actions
00264 
00265   action_.insert( "Background",        new QAction( "Background color", this ) );
00266   action_.insert( "Snapshot",          new QAction( "Snapshot", this ) );
00267   action_.insert( "SnapshotName",      new QAction( "Set snapshot name", this ) );
00268   action_.insert( "SnapshotSavesView", new QAction( "Snapshot saves view", this ) );
00269   action_.insert( "CopyView",          new QAction( "Copy view", this ) );
00270   action_.insert( "PasteView",         new QAction( "Paste view", this ) );
00271   action_.insert( "PasteDropSize",     new QAction( "Paste/Drop effects size", this ) );
00272   action_.insert( "Synchronize",       new QAction( "Synchronize", this ) );
00273   action_.insert( "Animation",         new QAction( "Animation", this ) );
00274   action_.insert( "BackfaceCulling",   new QAction( "Backface culling", this ) );
00275   action_.insert( "TwoSidedLighting",  new QAction( "Two-sided lighting", this ) );
00276 
00277   connect( action_["Background"], SIGNAL( triggered() ),
00278            this, SLOT( actionBackground() ) );
00279   connect( action_["Snapshot"], SIGNAL( triggered() ),
00280            this, SLOT( actionSnapshot() ) );
00281   connect( action_["SnapshotName"], SIGNAL( triggered() ),
00282            this, SLOT( actionSnapshotName() ) );
00283   connect( action_["SnapshotSavesView"], SIGNAL( triggered() ),
00284            this, SLOT( actionSnapshotSavesView() ) );
00285   connect( action_["CopyView"], SIGNAL( triggered() ),
00286            this, SLOT( actionCopyView() ) );
00287   connect( action_["PasteView"], SIGNAL( triggered() ),
00288            this, SLOT( actionPasteView() ) );
00289   connect( action_["PasteDropSize"], SIGNAL( triggered() ),
00290            this, SLOT( actionPasteDropSize() ) );
00291   connect( action_["Synchronize"], SIGNAL( triggered() ),
00292            this, SLOT( actionSynchronize() ) );
00293   connect( action_["Animation"], SIGNAL( triggered() ),
00294            this, SLOT( actionAnimation() ) );
00295   connect( action_["BackfaceCulling"], SIGNAL( triggered() ),
00296            this, SLOT( actionBackfaceCulling() ) );
00297   connect( action_["TwoSidedLighting"], SIGNAL( triggered() ),
00298            this, SLOT( actionTwoSidedLighting() ) );
00299 
00300   action_["SnapshotSavesView"]->setCheckable( true );
00301   action_["PasteDropSize"]->setCheckable( true );
00302   action_["Synchronize"]->setCheckable( true );
00303   action_["Animation"]->setCheckable( true );
00304   action_["BackfaceCulling"]->setCheckable( true );
00305   action_["TwoSidedLighting"]->setCheckable( true );
00306 
00307 
00308   QSizePolicy sp = sizePolicy();
00309   sp.setHorizontalPolicy( QSizePolicy::Expanding );
00310   sp.setVerticalPolicy( QSizePolicy::Expanding );
00311   sp.setHorizontalStretch( 1 );
00312   sp.setVerticalStretch( 1 );
00313   setSizePolicy( sp );
00314 
00315   redrawTime_.start ();
00316 
00317 }
00318 
00319 
00320 //-----------------------------------------------------------------------------
00321 
00322 
00323 QtBaseViewer::~QtBaseViewer()
00324 {
00325   delete privateStatusBar_;
00326   delete snapshot_;
00327   delete glstate_;
00328   delete sceneGraphDialog_;
00329   delete socket_;
00330   //  delete socket_notifier_;
00331 }
00332 
00333 
00334 //-----------------------------------------------------------------------------
00335 
00336 
00337 QSize
00338 QtBaseViewer::sizeHint() const
00339 {
00340   return QSize( 600, 600 );
00341 }
00342 
00343 
00344 //-----------------------------------------------------------------------------
00345 
00346 
00347 void QtBaseViewer::setStatusBar(QStatusBar* _sb)
00348 {
00349   if (_sb==0)
00350   {
00351     if (privateStatusBar_==0)
00352       privateStatusBar_=new QStatusBar(this);
00353     statusbar_=privateStatusBar_;
00354     if (options_ & ShowPrivateStatusBar)
00355       privateStatusBar_->show();
00356     else
00357       privateStatusBar_->hide();
00358   }
00359   else {
00360     statusbar_ = _sb;
00361   }
00362 }
00363 
00364 
00365 //-----------------------------------------------------------------------------
00366 
00367 
00368 void QtBaseViewer::applyOptions(int _options)
00369 {
00370   if (_options&ShowPrivateStatusBar)
00371     setStatusBar(0);
00372   else if (privateStatusBar_!=0)
00373     privateStatusBar_->hide();
00374 
00375   if (_options&ShowToolBar)        buttonBar_->show();
00376   else                             buttonBar_->hide();
00377   if (_options&ShowPickButton)     pickButton_->show();
00378   else                             pickButton_->hide();
00379   if (_options&ShowQuestionButton) questionButton_->show();
00380   else                             questionButton_->hide();
00381   if (_options&ShowWheelX)         wheelX_->show();
00382   else                             wheelX_->hide();
00383   if (_options&ShowWheelY)         wheelY_->show();
00384   else                             wheelY_->hide();
00385   if (_options&ShowWheelZ)         wheelZ_->show();
00386   else                             wheelZ_->hide();
00387 }
00388 
00389 
00390 //-----------------------------------------------------------------------------
00391 
00392 
00393 void QtBaseViewer::makeCurrent() {
00394   glWidget_->makeCurrent();
00395 }
00396 
00397 void QtBaseViewer::swapBuffers() {
00398   glWidget_->swapBuffers();
00399 }
00400 
00401 
00402 //-----------------------------------------------------------------------------
00403 
00404 
00405 void QtBaseViewer::sceneGraph(SceneGraph::BaseNode* _root)
00406 {
00407   sceneGraphRoot_ = _root;
00408 
00409   if (sceneGraphRoot_)
00410   {
00411     // get draw modes
00412     SceneGraph::CollectDrawModesAction action;
00413     SceneGraph::traverse(sceneGraphRoot_, action);
00414     availDrawModes_ = action.drawModes();
00415     updatePopupMenu();
00416 
00417     // get scene size
00418     SceneGraph::BoundingBoxAction act;
00419     SceneGraph::traverse(sceneGraphRoot_, act);
00420 
00421     Vec3d bbmin = (Vec3d) act.bbMin();
00422     Vec3d bbmax = (Vec3d) act.bbMax();
00423 
00424     if ( ( bbmin[0] > bbmax[0] ) ||
00425          ( bbmin[1] > bbmax[1] ) ||
00426          ( bbmin[2] > bbmax[2] )   )
00427       setScenePos( Vec3d( 0.0,0.0,0.0 ) , 1.0 );
00428     else
00429       setScenePos( ( bbmin + bbmax )        * 0.5,
00430                    ( bbmax - bbmin ).norm() * 0.5 );
00431   }
00432 
00433   updateGL();
00434 
00435   emit(signalSceneGraphChanged(sceneGraphRoot_));
00436 }
00437 
00438 
00439 //-----------------------------------------------------------------------------
00440 
00441 
00442 void QtBaseViewer::lockUpdate()
00443 {
00444   updateLocked_ = true;
00445   //  QToolTip::add(moveButton_, "Switch to <b>move</b> mode (display locked)");
00446 }
00447 
00448 
00449 void QtBaseViewer::unlockUpdate()
00450 {
00451   //  QToolTip::add(moveButton_,"Switch to <b>move</b> mode");
00452   updateLocked_ = false;
00453 }
00454 
00455 
00456 void QtBaseViewer::unlockAndUpdate()
00457 {
00458   unlockUpdate();
00459   updateGL();
00460 }
00461 
00462 
00463 //-----------------------------------------------------------------------------
00464 
00465 
00466 void QtBaseViewer::trackMouse(bool _track)
00467 {
00468   trackMouse_ = _track;
00469 }
00470 
00471 
00472 //-----------------------------------------------------------------------------
00473 
00474 
00475 void QtBaseViewer::enablePopupMenu(bool _enable)
00476 {
00477   popupEnabled_ = _enable;
00478 
00479   if ( popupEnabled_ ) {
00480     glView_->setContextMenuPolicy( Qt::DefaultContextMenu );
00481   } else {
00482     glView_->setContextMenuPolicy( Qt::CustomContextMenu );
00483   }
00484 
00485 }
00486 
00487 
00488 //-----------------------------------------------------------------------------
00489 
00490 void QtBaseViewer::perspectiveProjection()
00491 {
00492   projectionMode(PERSPECTIVE_PROJECTION);
00493   updateGL();
00494 }
00495 
00496 
00497 void QtBaseViewer::orthographicProjection()
00498 {
00499   projectionMode(ORTHOGRAPHIC_PROJECTION);
00500   updateGL();
00501 }
00502 
00503 
00504 void QtBaseViewer::toggleProjectionMode()
00505 {
00506   if (projectionMode_ == ORTHOGRAPHIC_PROJECTION)
00507     projectionMode(PERSPECTIVE_PROJECTION);
00508   else
00509     projectionMode(ORTHOGRAPHIC_PROJECTION);
00510 
00511   // sync
00512   emit(signalSetView(glstate_->modelview(), glstate_->inverse_modelview()));
00513   
00514   emit viewChanged();
00515 
00516   updateGL();
00517 }
00518 
00519 
00520 void QtBaseViewer::projectionMode(ProjectionMode _p)
00521 {
00522   if ((projectionMode_ = _p) == ORTHOGRAPHIC_PROJECTION)
00523     projectionButton_->setIcon( QPixmap(orthoIcon) );
00524   else
00525     projectionButton_->setIcon( QPixmap(perspectiveIcon) );
00526 
00527   updateProjectionMatrix();
00528 }
00529 
00530 void QtBaseViewer::toggleNavigationMode()
00531 {
00532   if (navigationMode_ == NORMAL_NAVIGATION)
00533     navigationMode(FIRSTPERSON_NAVIGATION);
00534   else
00535     navigationMode(NORMAL_NAVIGATION);
00536 }
00537 
00538 
00539 void QtBaseViewer::navigationMode(NavigationMode _n)
00540 {
00541   if ((navigationMode_ = _n) == NORMAL_NAVIGATION)
00542     emit navigationModeChanged( true );
00543   else
00544     emit navigationModeChanged( false );
00545 }
00546 
00547 
00548 void QtBaseViewer::updateProjectionMatrix()
00549 {
00550   if( projectionUpdateLocked_ )
00551     return;
00552 
00553   makeCurrent();
00554 
00555   glstate_->reset_projection();
00556 
00557   // In scereo mode we have to use a perspective matrix
00558   if (stereo_ || projectionMode_ == PERSPECTIVE_PROJECTION)
00559   {
00560     double aspect;
00561 
00562     if (isVisible() && glWidth() && glHeight())
00563       aspect = (double) glWidth() / (double) glHeight();
00564     else
00565       aspect = 1.0;
00566 
00567     glstate_->perspective(fovy_, (GLdouble) aspect,
00568                           near_, far_);
00569   }
00570   else
00571   {
00572     double aspect;
00573 
00574     if (isVisible() && glWidth() && glHeight())
00575       aspect = (double) glWidth() / (double) glHeight();
00576     else
00577       aspect = 1.0;
00578 
00579     glstate_->ortho( -orthoWidth_, orthoWidth_,
00580                      -orthoWidth_/aspect, orthoWidth_/aspect,
00581                      near_, far_ );
00582   }
00583   
00584 }
00585 
00586 
00587 //-----------------------------------------------------------------------------
00588 
00589 
00590 void QtBaseViewer::setScenePos(const ACG::Vec3d& _center, double _radius, const bool _setCenter)
00591 {
00592   if(_setCenter) {
00593     scene_center_ = trackball_center_ = _center;
00594   }
00595 
00596   scene_radius_ = trackball_radius_ = _radius;
00597 
00598   orthoWidth_ = 2.0   * scene_radius_;
00599   
00600   ACG::Vec3d c = glstate_->modelview().transform_point(scene_center_);
00601 
00602   // Set far plane
00603   far_    = std::max(0.0002f * scene_radius_,  -(c[2] - scene_radius_));
00604 
00605   // Set near plane
00606   near_   = std::max(0.0001f * scene_radius_,  -(c[2] + scene_radius_));
00607 
00608 
00609   updateProjectionMatrix();
00610   updateGL();
00611 }
00612 
00613 //-----------------------------------------------------------------------------
00614 
00615 void QtBaseViewer::setSceneCenter( const ACG::Vec3d& _center ) {
00616 
00617         scene_center_ = trackball_center_ = _center;
00618 }
00619 
00620 //----------------------------------------------------------------------------
00621 
00622 
00623 void QtBaseViewer::viewingDirection( const Vec3d& _dir, const Vec3d& _up )
00624 {
00625   // calc eye point for this direction
00626   ACG::Vec3d eye = scene_center_ - _dir*(3.0*scene_radius_);
00627 
00628   glstate_->reset_modelview();
00629   glstate_->lookAt((ACG::Vec3d)eye, (ACG::Vec3d)scene_center_, (ACG::Vec3d)_up);
00630   
00631   emit viewChanged();
00632 }
00633 
00634 
00635 //-----------------------------------------------------------------------------
00636 
00637 
00638 void QtBaseViewer::actionMode(ActionMode _am)
00639 {
00640   moveButton_->setDown(false);
00641   lightButton_->setDown(false);
00642   pickButton_->setDown(false);
00643   questionButton_->setDown(false);
00644 
00645   trackMouse(false);
00646 
00647 
00648   if (_am != actionMode_)
00649   {
00650     lastActionMode_ = actionMode_;
00651     actionMode_ = _am;
00652   }
00653 
00654 
00655   switch (actionMode_)
00656   {
00657     case ExamineMode:
00658     {
00659       glView_->setCursor(Qt::PointingHandCursor);
00660       glBase_->setCursor(Qt::PointingHandCursor);
00661       moveButton_->setDown(true);
00662       break;
00663     }
00664 
00665 
00666     case LightMode:
00667     {
00668       glView_->setCursor(Qt::PointingHandCursor);
00669       glBase_->setCursor(Qt::PointingHandCursor);
00670       lightButton_->setDown(true);
00671       break;
00672     }
00673 
00674 
00675     case PickingMode:
00676     {
00677       glView_->setCursor(Qt::ArrowCursor);
00678       glBase_->setCursor(Qt::ArrowCursor);
00679       pickButton_->setDown(true);
00680       if (pick_mode_idx_ != -1) {
00681              trackMouse(pick_modes_[pick_mode_idx_].tracking);
00682         glView_->setCursor(pick_modes_[pick_mode_idx_].cursor);
00683         glBase_->setCursor(pick_modes_[pick_mode_idx_].cursor);
00684       }
00685 
00686       break;
00687     }
00688 
00689 
00690     case QuestionMode:
00691     {
00692       glView_->setCursor(Qt::WhatsThisCursor);
00693       glBase_->setCursor(Qt::WhatsThisCursor);
00694       questionButton_->setDown(true);
00695       break;
00696     }
00697   }
00698 
00699 
00700   emit(signalActionModeChanged(actionMode_));
00701 
00702   //emit pickmodeChanged with either the name of the current pickmode or an empty string
00703   if(actionMode_ == PickingMode)
00704     emit(signalPickModeChanged(pick_mode_name_));
00705   else
00706     emit(signalPickModeChanged(""));
00707 }
00708 
00709 
00710 //-----------------------------------------------------------------------------
00711 
00712 
00713 void QtBaseViewer::faceOrientation(FaceOrientation _ori)
00714 {
00715   makeCurrent();
00716 
00717   switch ( faceOrientation_ = _ori ) {
00718     case CCW_ORIENTATION:
00719       glFrontFace( GL_CCW );
00720       break;
00721 
00722     case CW_ORIENTATION:
00723       glFrontFace( GL_CW );
00724       break;
00725   }
00726 
00727   updateGL();
00728 }
00729 
00730 
00731 //-----------------------------------------------------------------------------
00732 
00733 
00734 void QtBaseViewer::backFaceCulling(bool _b)
00735 {
00736   makeCurrent();
00737   if (funcMenu_==0)  updatePopupMenu();
00738   if ( (backFaceCulling_ = _b) )
00739     glEnable( GL_CULL_FACE );
00740   else
00741     glDisable( GL_CULL_FACE );
00742 
00743   action_["BackfaceCulling"]->setChecked( backFaceCulling_ );
00744   updateGL();
00745 }
00746 
00747 
00748 void QtBaseViewer::twoSidedLighting(bool _b)
00749 {
00750   makeCurrent();
00751   if (funcMenu_==0)  updatePopupMenu();
00752   glstate_->set_twosided_lighting(twoSidedLighting_=_b);
00753   action_["TwoSidedLighting"]->setChecked(twoSidedLighting_);
00754   updateGL();
00755 }
00756 
00757 
00758 void QtBaseViewer::animation(bool _b)
00759 {
00760   makeCurrent();
00761   if (funcMenu_==0)  updatePopupMenu();
00762   animation_ = _b;
00763   action_["Animation"]->setChecked( animation_ );
00764   updateGL();
00765 }
00766 
00767 
00768 //-----------------------------------------------------------------------------
00769 
00770 
00771 void QtBaseViewer::normalsMode(NormalsMode _mode)
00772 {
00773   makeCurrent();
00774 
00775   switch(normalsMode_ = _mode)
00776   {
00777     case DONT_TOUCH_NORMALS:
00778       glDisable(GL_NORMALIZE);
00779       break;
00780 
00781     case NORMALIZE_NORMALS:
00782       glEnable(GL_NORMALIZE);
00783       break;
00784   }
00785 
00786   updateGL();
00787 }
00788 
00789 
00790 //-----------------------------------------------------------------------------
00791 
00792 
00793 void
00794 QtBaseViewer::copyToImage( QImage& _image,
00795                            unsigned int /* _l */ , unsigned int /* _t */ ,
00796                            unsigned int /* _w */ , unsigned int /* _h */ ,
00797                            GLenum /* _buffer */ )
00798 {
00799   makeCurrent();
00800   _image = glWidget_->grabFrameBuffer(true);
00801 }
00802 
00803 
00804 //-----------------------------------------------------------------------------
00805 
00806 
00807 void QtBaseViewer::drawNow()
00808 {
00809   makeCurrent();
00810   paintGL();
00811   swapBuffers();
00812   glView_->repaint();
00813 }
00814 
00815 void QtBaseViewer::updateGL()
00816 {
00817   if (!isUpdateLocked() && !isHidden() )
00818   {
00819     glScene_->update();
00820   }
00821 }
00822 
00823 
00824 
00825 //-----------------------------------------------------------------------------
00826 
00827 
00828 void QtBaseViewer::drawScene()
00829 {
00830   QTime  timer;
00831   timer.start();
00832 
00833 
00834   // *****************************************************************
00835   // Adjust clipping planes
00836   // *****************************************************************
00837   // Far plane
00838   ACG::Vec3d c = glstate_->modelview().transform_point(scene_center_);
00839   
00840   // Set far plane
00841   far_    = std::max(0.0002f * scene_radius_,  -(c[2] - scene_radius_));
00842   
00843   // Set near plane
00844   near_   = std::max(0.0001f * scene_radius_,  -(c[2] + scene_radius_));
00845   
00846   
00847   updateProjectionMatrix();
00848 
00849   // store time since last repaint in gl state and restart timer
00850   glstate_->set_msSinceLastRedraw (redrawTime_.restart ());
00851 
00852   // draw mono or stereo
00853   makeCurrent();
00854   if (stereo_) drawScene_stereo();
00855   else         drawScene_mono();
00856 
00857 
00858   glFinish();
00859   frame_time_ = timer.elapsed();
00860 }
00861 
00862 
00863 //-----------------------------------------------------------------------------
00864 
00865 
00866 void QtBaseViewer::drawScene_mono()
00867 {
00868   emit(signalDrawScene(glstate_));
00869 
00870   if (sceneGraphRoot_)
00871   {
00872     if (! renderPicking_ ) {
00873       SceneGraph::DrawAction action(curDrawMode_, false);
00874       SceneGraph::traverse(sceneGraphRoot_, action, *glstate_, curDrawMode_);
00875 
00876       if( blending_ )
00877       {
00878         SceneGraph::DrawAction action(curDrawMode_, true);
00879         SceneGraph::traverse(sceneGraphRoot_, action, *glstate_, curDrawMode_);
00880       }
00881     } else {
00882 
00883       // prepare GL state
00884       makeCurrent();
00885 
00886       glDisable(GL_LIGHTING);
00887       glClear(GL_DEPTH_BUFFER_BIT);
00888       glInitNames();
00889       glPushName((GLuint) 0);
00890 
00891       // do the picking
00892       SceneGraph::PickAction action(*glstate_, pickRendererMode_, curDrawMode_);
00893       SceneGraph::traverse(sceneGraphRoot_, action);
00894 
00895       glEnable(GL_LIGHTING);
00896     }
00897   }
00898 }
00899 
00900 
00901 //-----------------------------------------------------------------------------
00902 
00903 
00904 void
00905 QtBaseViewer::drawScene_stereo()
00906 {
00907   double l, r, t, b, w, h, a, radians, wd2, ndfl;
00908 
00909   w = glWidth();
00910   h = glHeight();
00911   a = w / h;
00912 
00913   radians = fovy_ * 0.5 / 180.0 * M_PI;
00914   wd2     = near_ * tan(radians);
00915   ndfl    = near_ / focalDist_ * scene_radius_;
00916 
00917   l = -a*wd2;
00918   r =  a*wd2;
00919   t =  wd2;
00920   b = -wd2;
00921 
00922   double offset  = 0.5 * eyeDist_;
00923   double offset2 = offset * ndfl;
00924 
00925 
00926 
00927   // left eye
00928   glMatrixMode(GL_PROJECTION);
00929   glLoadIdentity();
00930   glFrustum(l+offset2, r+offset2, b, t, near_, far_);
00931   glTranslatef(-offset, 0.0, 0.0);
00932   glMatrixMode(GL_MODELVIEW);
00933   glDrawBuffer(GL_BACK_LEFT);
00934   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00935   drawScene_mono();
00936 
00937 
00938   // right eye
00939   glMatrixMode(GL_PROJECTION);
00940   glLoadIdentity();
00941   glFrustum(l-offset2, r-offset2, b, t, near_, far_);
00942   glTranslatef(offset, 0.0, 0.0);
00943   glMatrixMode(GL_MODELVIEW);
00944   glDrawBuffer(GL_BACK_RIGHT);
00945   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00946   drawScene_mono();
00947   glDrawBuffer(GL_BACK);
00948 }
00949 
00950 
00951 
00952 //-----------------------------------------------------------------------------
00953 
00954 
00955 void QtBaseViewer::setHome()
00956 {
00957   home_modelview_          = glstate_->modelview();
00958   home_inverse_modelview_  = glstate_->inverse_modelview();
00959   homeOrthoWidth_          = orthoWidth_;
00960   home_center_             = trackball_center_;
00961   home_radius_             = trackball_radius_;
00962 }
00963 
00964 
00965 void QtBaseViewer::home()
00966 {
00967   makeCurrent();
00968   glstate_->set_modelview(home_modelview_, home_inverse_modelview_);
00969   orthoWidth_ = homeOrthoWidth_;
00970   trackball_center_ = home_center_;
00971   trackball_radius_ = home_radius_;
00972   updateProjectionMatrix();
00973   updateGL();
00974 
00975   // sync
00976   emit(signalSetView(glstate_->modelview(), glstate_->inverse_modelview()));
00977   
00978   emit viewChanged();
00979 }
00980 
00981 
00982 //-----------------------------------------------------------------------------
00983 
00984 
00985 void QtBaseViewer::viewAll()
00986 {
00987   makeCurrent();
00988 
00989   // move center (in camera coords) to origin and translate in -z dir
00990   translate(-(glstate_->modelview().transform_point(scene_center_))
00991             - Vec3d(0.0, 0.0, 3.0*scene_radius_ ));
00992 
00993   orthoWidth_ = 1.1*scene_radius_;
00994   double aspect = (double) glWidth() / (double) glHeight();
00995   if (aspect > 1.0) orthoWidth_ *= aspect;
00996   updateProjectionMatrix();
00997   updateGL();
00998 
00999   // sync
01000   emit(signalSetView(glstate_->modelview(), glstate_->inverse_modelview()));
01001   
01002   emit viewChanged();
01003 }
01004 
01005 
01006 //-----------------------------------------------------------------------------
01007 
01008 
01009 void QtBaseViewer::flyTo(const QPoint& _pos, bool _move_back)
01010 {
01011   makeCurrent();
01012 
01013   unsigned int nodeIdx, targetIdx;
01014   Vec3d hitPoint;
01015 
01016   if (pick(SceneGraph::PICK_ANYTHING, _pos, nodeIdx, targetIdx, &hitPoint))
01017   {
01018     if (projectionMode_ == PERSPECTIVE_PROJECTION)
01019     {
01020       Vec3d eye(glState().eye());
01021       Vec3d t = hitPoint - eye;
01022       Vec3d e = eye + t * (_move_back ? -0.5f : 0.5f);
01023       flyTo(e, hitPoint, 300);
01024     }
01025     else
01026     {
01027       // Zoom in or out?
01028       orthoWidth_ *= _move_back ? 2.0 : 0.5;
01029 
01030       // Set the double click point as the new trackball center
01031       // Rotations will use this point as the center.
01032       trackball_center_ = hitPoint;
01033 
01035 
01036       // Update the projection matrix
01037       updateProjectionMatrix();
01038 
01039       // Redraw scene
01040       updateGL();
01041     }
01042 
01043     // sync with external viewer
01044     emit(signalSetView(glstate_->modelview(), glstate_->inverse_modelview()));
01045     
01046     emit viewChanged();
01047   }
01048 }
01049 
01050 
01051 void QtBaseViewer::flyTo(const Vec3d&  _position,
01052                          const Vec3d&  _center,
01053                          double        _time)
01054 {
01055   makeCurrent();
01056 
01057   // compute rotation
01058   Vec3d c = glstate_->modelview().transform_point(_center);
01059   Vec3d p = glstate_->modelview().transform_point(_position);
01060   Vec3d view =(p-c).normalize();
01061   Vec3d z(0,0,1);
01062   Vec3d axis = (z % -view).normalize();
01063   double angle = acos(std::max(-1.0,
01064                               std::min(1.0,
01065                                        (z | view)))) / M_PI * 180.0;
01066 
01067   if (angle > 175)
01068     axis  = Vec3d(0,1,0);
01069 
01070 
01071   // compute translation
01072   Vec3d target = glstate_->modelview().transform_point(_center);
01073   Vec3d trans ( -target[0],
01074                 -target[1],
01075                 -target[2] - (_position-_center).norm() );
01076 
01077 
01078 
01079   // how many frames in _time ms ?
01080   unsigned int  frames = (unsigned int)(_time / frame_time_);
01081   if (frames > 1000) frames=1000;
01082 
01083 
01084 
01085 
01086   // animate it
01087   if (frames > 10)
01088   {
01089     Vec3d t = trans / (double)frames;
01090     double a = angle / (double)frames;
01091 
01092     for (unsigned int i=0; i<frames; ++i)
01093     {
01094       translate(t);
01095       if (fabs(a) > FLT_MIN)
01096              rotate(axis, a, _center);
01097 
01098       drawNow();
01099     }
01100   }
01101 
01102 
01103   // no animation
01104   else
01105   {
01106     translate(trans);
01107     if (fabs(angle) > FLT_MIN)
01108       rotate(axis, angle, _center);
01109 
01110     updateGL();
01111   }
01112 
01113 
01114   trackball_center_ = _center;
01115   trackball_radius_ = std::max(scene_radius_,
01116                                (_center-_position).norm()*0.9f);
01117 }
01118 
01119 
01120 //-----------------------------------------------------------------------------
01121 
01122 
01123 void QtBaseViewer::setView(const GLMatrixd& _modelview,
01124                            const GLMatrixd& _inverse_modelview)
01125 {
01126   makeCurrent();
01127   glstate_->set_modelview(_modelview, _inverse_modelview);
01128   updateGL();
01129 }
01130 
01131 
01132 //-----------------------------------------------------------------------------
01133 
01134 
01135 void QtBaseViewer::initializeGL()
01136 {
01137   // we use GLEW to manage extensions
01138   // initialize it first
01139   glewInit();
01140 
01141 
01142   // lock update
01143   lockUpdate();
01144 
01145   // init GL state
01146   glstate_->initialize();
01147 
01148   // OpenGL state
01149   glEnable(GL_DEPTH_TEST);
01150   glEnable(GL_LIGHTING);
01151   glDisable(GL_DITHER);
01152   glShadeModel( GL_FLAT );
01153 
01154 
01155   projectionMode(   projectionMode_   );
01156   normalsMode(      normalsMode_      );
01157   faceOrientation(  faceOrientation_  );
01158   backFaceCulling(  backFaceCulling_  );
01159   twoSidedLighting( twoSidedLighting_ );
01160 
01161 
01162   // light sources
01163   light_matrix_.identity();
01164   update_lights();
01165 
01166 
01167   // scene pos and size
01168   scene_center_ = trackball_center_ = Vec3d( 0.0, 0.0, 0.0 );
01169   scene_radius_ = trackball_radius_ = 1.0;
01170   orthoWidth_   = 2.0;
01171 
01172 
01173   // modelview
01174   glstate_->translate(0.0, 0.0, -3.0);
01175   setHome();
01176 
01177 
01178   // pixel transfer
01179   glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
01180   glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
01181   glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
01182   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01183   glPixelStorei(GL_PACK_ROW_LENGTH, 0);
01184   glPixelStorei(GL_PACK_SKIP_ROWS, 0);
01185   glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
01186   glPixelStorei(GL_PACK_ALIGNMENT, 1);
01187 
01188 
01189   // emit initialization signal
01190   emit(signalInitializeGL());
01191 
01192 
01193   // unlock update (we started locked)
01194   unlockUpdate();
01195 }
01196 
01197 
01198 //-----------------------------------------------------------------------------
01199 
01200 
01201 void QtBaseViewer::update_lights()
01202 {
01203   makeCurrent();
01204 
01205   glMatrixMode(GL_MODELVIEW);
01206   glPushMatrix();
01207   glLoadIdentity();
01208   glMultMatrixd(light_matrix_.data());
01209 
01210   GLfloat pos[4], col[4];
01211 
01212   col[0] = col[1] = col[2] = 0.7;
01213   pos[3] = col[3] = 0.0;
01214 
01215 #define SET_LIGHT(i,x,y,z) {                    \
01216     pos[0]=x; pos[1]=y; pos[2]=z;               \
01217     glLightfv(GL_LIGHT##i, GL_POSITION, pos);   \
01218     glLightfv(GL_LIGHT##i, GL_DIFFUSE,  col);   \
01219     glLightfv(GL_LIGHT##i, GL_SPECULAR, col);   \
01220     glEnable(GL_LIGHT##i);                      \
01221   }
01222 
01223   SET_LIGHT(0,  0.0,  0.0, 1.0);
01224   SET_LIGHT(1, -1.0,  1.0, 0.7);
01225   SET_LIGHT(2,  1.0,  1.0, 0.7);
01226 
01227   col[0] = col[1] = col[2] = 0.3; col[3] = 1.0;
01228   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
01229 
01230   glPopMatrix();
01231 }
01232 
01233 
01234 void QtBaseViewer::rotate_lights(Vec3d& _axis, double _angle)
01235 {
01236   light_matrix_.rotate(_angle, _axis[0], _axis[1], _axis[2], MULT_FROM_LEFT);
01237   update_lights();
01238 }
01239 
01240 
01241 //-----------------------------------------------------------------------------
01242 
01243 
01244 void QtBaseViewer::paintGL()
01245 {
01246   static bool initialized = false;
01247   if (!initialized)
01248   {
01249     // we use GLEW to manage extensions
01250     // initialize it first
01251     glewInit();
01252 
01253     // lock update
01254     lockUpdate();
01255 
01256     // init GL state
01257     glstate_->initialize();
01258 
01259     // initialize lights
01260     light_matrix_.identity();
01261 
01262     // scene pos and size
01263     scene_center_ = trackball_center_ = Vec3d( 0.0, 0.0, 0.0 );
01264     scene_radius_ = trackball_radius_ = 1.0;
01265     orthoWidth_   = 2.0;
01266 
01267     // modelview
01268     glstate_->translate(0.0, 0.0, -3.0);
01269     setHome();
01270 
01271     // pixel transfer
01272     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
01273     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
01274     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
01275     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01276     glPixelStorei(GL_PACK_ROW_LENGTH, 0);
01277     glPixelStorei(GL_PACK_SKIP_ROWS, 0);
01278     glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
01279     glPixelStorei(GL_PACK_ALIGNMENT, 1);
01280 
01281     // emit initialization signal
01282     emit(signalInitializeGL());
01283 
01284     // unlock update (we started locked)
01285     unlockUpdate();
01286 
01287     initialized = true;
01288   }
01289 
01290   if (!isUpdateLocked())
01291   {
01292     lockUpdate();
01293 
01294     glPushAttrib (GL_ALL_ATTRIB_BITS);
01295 
01296     glEnable(GL_DEPTH_TEST);
01297     glEnable(GL_LIGHTING);
01298     glDisable(GL_DITHER);
01299     glShadeModel( GL_FLAT );
01300 
01301     glMatrixMode(GL_PROJECTION);
01302     glPushMatrix();
01303 
01304     glMatrixMode(GL_MODELVIEW);
01305     glPushMatrix();
01306 
01307 
01308     normalsMode(      normalsMode_      );
01309     faceOrientation(  faceOrientation_  );
01310     backFaceCulling(  backFaceCulling_  );
01311 
01312     // light sources
01313     update_lights();
01314 
01315     glstate_->setState ();
01316 
01317     glColor4f(1.0,0.0,0.0,1.0);
01318 
01319     // clear (stereo mode clears buffers on its own)
01320     if (!stereo_)
01321       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01322 
01323     unlockUpdate();
01324 
01325     // draw scene
01326     drawScene();
01327 
01328     glPopMatrix();
01329 
01330     glMatrixMode(GL_PROJECTION);
01331     glPopMatrix();
01332 
01333     glPopAttrib ();
01334   }
01335 }
01336 
01337 
01338 //-----------------------------------------------------------------------------
01339 
01340 
01341 void QtBaseViewer::resizeGL(int _w, int _h)
01342 {
01343   updateProjectionMatrix();
01344   glstate_->viewport(0, 0, _w, _h);
01345   updateGL();
01346 }
01347 
01348 
01349 //-----------------------------------------------------------------------------
01350 
01351 void QtBaseViewer::encodeView(QString& _view)
01352 {
01353   // Get current matrices
01354   const ACG::GLMatrixd m = glstate_->modelview();
01355   const ACG::GLMatrixd p = glstate_->projection();
01356 
01357   // Add modelview matrix to output
01358   _view += QString(VIEW_MAGIC) + "\n";
01359   _view += QString::number(m(0,0)) + " " + QString::number(m(0,1)) + " " + QString::number(m(0,2)) + " " + QString::number(m(0,3)) + "\n";
01360   _view += QString::number(m(1,0)) + " " + QString::number(m(1,1)) + " " + QString::number(m(1,2)) + " " + QString::number(m(1,3)) + "\n";
01361   _view += QString::number(m(2,0)) + " " + QString::number(m(2,1)) + " " + QString::number(m(2,2)) + " " + QString::number(m(2,3)) + "\n";
01362   _view += QString::number(m(3,0)) + " " + QString::number(m(3,1)) + " " + QString::number(m(3,2)) + " " + QString::number(m(3,3)) + "\n";
01363 
01364   // Add projection matrix to output
01365   _view += QString::number(p(0,0)) + " " + QString::number(p(0,1)) + " " + QString::number(p(0,2)) + " " + QString::number(p(0,3)) + "\n";
01366   _view += QString::number(p(1,0)) + " " + QString::number(p(1,1)) + " " + QString::number(p(1,2)) + " " + QString::number(p(1,3)) + "\n";
01367   _view += QString::number(p(2,0)) + " " + QString::number(p(2,1)) + " " + QString::number(p(2,2)) + " " + QString::number(p(2,3)) + "\n";
01368   _view += QString::number(p(3,0)) + " " + QString::number(p(3,1)) + " " + QString::number(p(3,2)) + " " + QString::number(p(3,3)) + "\n";
01369 
01370   // add gl width/height, current projection Mode and the ortho mode width to output
01371   _view += QString::number(glWidth()) + " " +  QString::number(glHeight()) + " " + QString::number(projectionMode_) + " " + QString::number(orthoWidth_) + "\n";
01372 }
01373 
01374 
01375 //----------------------------------------------------------------------------
01376 
01377 
01378 bool QtBaseViewer::decodeView(const QString& _view)
01379 {
01380   if (_view.left(sizeof(VIEW_MAGIC)-1) != QString(VIEW_MAGIC))
01381     return false;
01382 
01383   // Remove the magic from the string
01384   QString temp = _view;
01385   temp.remove(0,sizeof(VIEW_MAGIC));
01386 
01387   //Split it into its components
01388   QStringList split = temp.split(QRegExp("[\\n\\s]"),QString::SkipEmptyParts);
01389 
01390   ACG::GLMatrixd m, p;
01391   int            w, h, pMode;
01392 
01393   // Check if the number of components matches the expected size
01394   if ( split.size() != 36 ) {
01395     std::cerr << "Unable to paste view ... wrong parameter count!! is" <<  split.size()  << std::endl;
01396     return false;
01397   }
01398 
01399   // Parse the components
01400   bool ok = true;;
01401 
01402   m(0,0) = split[0].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01403   m(0,1) = split[1].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01404   m(0,2) = split[2].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01405   m(0,3) = split[3].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01406   m(1,0) = split[4].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01407   m(1,1) = split[5].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01408   m(1,2) = split[6].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01409   m(1,3) = split[7].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01410   m(2,0) = split[8].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01411   m(2,1) = split[9].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01412   m(2,2) = split[10].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01413   m(2,3) = split[11].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01414   m(3,0) = split[12].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01415   m(3,1) = split[13].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01416   m(3,2) = split[14].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01417   m(3,3) = split[15].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01418   p(0,0) = split[16].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01419   p(0,1) = split[17].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01420   p(0,2) = split[18].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01421   p(0,3) = split[19].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01422   p(1,0) = split[20].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01423   p(1,1) = split[21].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01424   p(1,2) = split[22].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01425   p(1,3) = split[23].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01426   p(2,0) = split[24].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01427   p(2,1) = split[25].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01428   p(2,2) = split[26].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01429   p(2,3) = split[27].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01430   p(3,0) = split[28].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01431   p(3,1) = split[29].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01432   p(3,2) = split[30].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01433   p(3,3) = split[31].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01434 
01435   w =  split[32].toInt(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01436   h =  split[33].toInt(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01437   pMode =  split[34].toInt(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01438   orthoWidth_ = split[35].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
01439 
01440   // Switch to our gl context
01441   makeCurrent();
01442 
01443   // set projection mode
01444   if (projectionMode_ != (ProjectionMode)pMode)
01445     projectionMode((ProjectionMode)pMode);
01446 
01447   // Apply new modelview matrix
01448   glstate_->set_modelview(m);
01449 
01450 
01451   if (w>0 && h>0 &&
01452       action_["PasteDropSize"]->isChecked() )
01453   {
01454     glstate_->set_projection(p);
01455     glView_->setFixedSize(w,h);
01456     updateGeometry();
01457   }
01458 
01459 
01460   updateGL();
01461 
01462 
01463   return true;
01464 }
01465 
01466 
01467 //-----------------------------------------------------------------------------
01468 
01469 
01470 void QtBaseViewer::actionDrawMenu( QAction * _action )
01471 {
01472   unsigned int mode( _action->data().toUInt() );
01473 
01474   // combine draw modes
01475   if (qApp->keyboardModifiers() & Qt::ShiftModifier)
01476   {
01477     if (drawMode() & mode)
01478       drawMode(drawMode() & ~mode);
01479     else
01480       drawMode(drawMode() | mode);
01481   }
01482 
01483   // simply switch draw mode
01484   else
01485   {
01486     // clear all other checked items
01487     std::vector< QAction * >::iterator aIter, aEnd;
01488 
01489     aEnd = drawMenuActions_.end();
01490     for( aIter = drawMenuActions_.begin();
01491          aIter != aEnd;
01492          ++aIter )
01493     {
01494       if( (*aIter)->data().toUInt() != mode )
01495           (*aIter)->setChecked( false );
01496     }
01497 
01498     drawMode(mode);
01499   }
01500 
01501   hidePopupMenus();
01502   updateGL();
01503 }
01504 
01505 
01506 //-----------------------------------------------------------------------------
01507 
01508 
01509 void QtBaseViewer::actionBackground()
01510 {
01511   const Vec4f bc = glstate_->clear_color() * 255.0;
01512   QColor backCol((int)bc[0], (int)bc[1], (int)bc[2]);
01513   QColor c = QColorDialog::getColor(backCol,this);
01514   if (c != backCol && c.isValid())
01515     backgroundColor(Vec4f(((double) c.red())   / 255.0,
01516                           ((double) c.green()) / 255.0,
01517                           ((double) c.blue())  / 255.0,
01518                           1.0));
01519 
01520 }
01521 
01522 //-----------------------------------------------------------------------------
01523 
01524 
01525 void QtBaseViewer::actionCopyView()
01526 {
01527   QString view; encodeView(view);
01528   QApplication::clipboard()->setText(view);
01529 }
01530 
01531 
01532 //-----------------------------------------------------------------------------
01533 
01534 
01535 void QtBaseViewer::actionPasteView()
01536 {
01537   QString view; view=QApplication::clipboard()->text();
01538   decodeView(view);
01539 }
01540 
01541 
01542 //-----------------------------------------------------------------------------
01543 
01544 
01545 void QtBaseViewer::actionPasteDropSize()
01546 {
01547 }
01548 
01549 //-----------------------------------------------------------------------------
01550 
01551 
01552 void QtBaseViewer::actionSynchronize()
01553 {
01554   setSynchronization( action_["Synchronize"]->isChecked() );
01555 }
01556 
01557 //-----------------------------------------------------------------------------
01558 
01559 void QtBaseViewer::actionSynchronize(bool _enable)
01560 {
01561   setSynchronization( _enable );
01562 }
01563 
01564 bool QtBaseViewer::synchronization(){
01565   return synchronized_;
01566 }
01567 
01568 //-----------------------------------------------------------------------------
01569 
01570 void QtBaseViewer::actionAnimation()
01571 {
01572   animation(!animation());
01573 }
01574 
01575 //-----------------------------------------------------------------------------
01576 
01577 void QtBaseViewer::actionAnimation(bool _enable)
01578 {
01579   animation(_enable);
01580 }
01581 
01582 //-----------------------------------------------------------------------------
01583 
01584 void QtBaseViewer::actionBackfaceCulling()
01585 {
01586   backFaceCulling(!backFaceCulling());
01587 }
01588 
01589 //-----------------------------------------------------------------------------
01590 
01591 void QtBaseViewer::actionBackfaceCulling(bool _enable)
01592 {
01593   backFaceCulling(_enable);
01594 }
01595 
01596 //-----------------------------------------------------------------------------
01597 
01598 void QtBaseViewer::actionTwoSidedLighting()
01599 {
01600   twoSidedLighting(!twoSidedLighting());
01601 }
01602 
01603 //-----------------------------------------------------------------------------
01604 
01605 void QtBaseViewer::actionTwoSidedLighting(bool _enable)
01606 {
01607   twoSidedLighting(_enable);
01608 }
01609 
01610 //-----------------------------------------------------------------------------
01611 
01612 void
01613 QtBaseViewer::createWidgets(const QGLFormat* _format,
01614                             QStatusBar* _sb,
01615                             const QtBaseViewer* _share)
01616 {
01617   statusbar_=privateStatusBar_=0;
01618   setStatusBar(_sb);
01619   drawMenu_=0;
01620   funcMenu_=0;
01621   pickMenu_=0;
01622 
01623 
01624   // contains splitter and eventually status bar
01625   // QT3:  Q3VBoxLayout* layout=new Q3VBoxLayout(this,0,0,"toplevel layout");
01626   QVBoxLayout* layout=new QVBoxLayout(this);
01627   layout->setSpacing( 0 );
01628   layout->setMargin( 0 );
01629 
01630   // contains glarea and buttons
01631 
01632   // QT3:  Q3Frame* work=new Q3Frame(this,"box-glarea-buttons");
01633   QFrame* work=new QFrame(this);
01634 
01635   layout->addWidget(work,1); // gets all stretch
01636 
01637 
01638   // private status bar
01639   assert(statusbar_!=0);
01640   if (privateStatusBar_!=0)
01641     layout->addWidget(privateStatusBar_,0); // no stretch
01642 
01643 
01644   // Construct GL context & widget
01645   QGLWidget* share = 0;
01646   if (_share)  share = _share->glWidget_;
01647 
01648   QGLFormat format;
01649   format.setAlpha(true);
01650   if (_format!=0) format = *_format;
01651 
01652   glWidget_ = new QGLWidget(format, 0, share);
01653   glView_ = new QtGLGraphicsView(this, work);
01654   glScene_ = new QtGLGraphicsScene (this);
01655 
01656   glView_->setViewport(glWidget_);
01657   glView_->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
01658   glView_->setScene(glScene_);
01659 
01660   wheelZ_=new QtWheel( 0,"wheel-z",QtWheel::Vertical);
01661   wheelZ_->setMinimumSize(wheelZ_->sizeHint());
01662   wheelZ_->setMaximumSize(wheelZ_->sizeHint());
01663   connect(wheelZ_,SIGNAL(angleChangedBy(double)),
01664           this,SLOT(slotWheelZ(double)));
01665   wheelZ_->setToolTip( "Translate along <b>z-axis</b>.");
01666   wheelZ_->setWhatsThis( "Translate along <b>z-axis</b>.");
01667   if ((options_&ShowWheelZ)==0)
01668     wheelZ_->hide();
01669 
01670   wheelY_=new QtWheel( 0,"wheel-y",QtWheel::Horizontal);
01671   wheelY_->setMinimumSize(wheelY_->sizeHint());
01672   wheelY_->setMaximumSize(wheelY_->sizeHint());
01673   connect(wheelY_,SIGNAL(angleChangedBy(double)),
01674           this,SLOT(slotWheelY(double)));
01675   wheelY_->setToolTip("Rotate around <b>y-axis</b>.");
01676   wheelY_->setWhatsThis( "Rotate around <b>y-axis</b>.");
01677   if ((options_&ShowWheelY)==0)
01678     wheelY_->hide();
01679 
01680   wheelX_=new QtWheel( 0,"wheel-x",QtWheel::Vertical);
01681   wheelX_->setMinimumSize(wheelX_->sizeHint());
01682   wheelX_->setMaximumSize(wheelX_->sizeHint());
01683   connect(wheelX_,SIGNAL(angleChangedBy(double)),
01684           this,SLOT(slotWheelX(double)));
01685   wheelX_->setToolTip("Rotate around <b>x-axis</b>.");
01686   wheelX_->setWhatsThis( "Rotate around <b>x-axis</b>.");
01687   if ((options_&ShowWheelX)==0)
01688     wheelX_->hide();
01689 
01690 
01691   QGraphicsWidget *wheelX = glScene_->addWidget (wheelX_);
01692   QGraphicsWidget *wheelY = glScene_->addWidget (wheelY_);
01693   QGraphicsWidget *wheelZ = glScene_->addWidget (wheelZ_);
01694 
01695   wheelX_->setWindowOpacity (0.5);
01696   wheelY_->setWindowOpacity (0.5);
01697   wheelZ_->setWindowOpacity (0.5);
01698 
01699   wheelX->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
01700   wheelY->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
01701   wheelZ->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
01702 
01703   glBaseLayout_ = new QGraphicsGridLayout;
01704   glBaseLayout_->addItem(wheelX, 1, 0);
01705   glBaseLayout_->addItem(wheelY, 2, 1);
01706   glBaseLayout_->addItem(wheelZ, 1, 3);
01707 
01708   glBaseLayout_->setColumnStretchFactor(0,0);
01709   glBaseLayout_->setColumnStretchFactor(1,0);
01710   glBaseLayout_->setColumnStretchFactor(2,1);
01711   glBaseLayout_->setColumnStretchFactor(3,0);
01712 
01713   glBaseLayout_->setRowStretchFactor(0,1);
01714   glBaseLayout_->setRowStretchFactor(1,0);
01715   glBaseLayout_->setRowStretchFactor(2,0);
01716 
01717   glBase_ = new QGraphicsWidget;
01718   glBase_->setLayout(glBaseLayout_);
01719   glScene_->addItem(glBase_);
01720   glBase_->setGeometry (glScene_->sceneRect ());
01721   QRectF r = glScene_->sceneRect ();
01722 
01723   connect ( glScene_, SIGNAL( sceneRectChanged( const QRectF & ) ),
01724             this, SLOT( sceneRectChanged( const QRectF & ) ) );
01725 
01726   // If popupEnabled_ this signal will not be emitted!
01727   // If popupEnabled_ is set to false the Contextmenu Mode will be set to customContextMenuRequested
01728   // and this signal will be emitted on right click
01729   connect( glView_ , SIGNAL( customContextMenuRequested( const QPoint& ) ) ,
01730            this    , SIGNAL( signalCustomContextMenuRequested( const QPoint& ) ) );
01731 
01732   // is stereo possible ?
01733   if (format.stereo())
01734     std::cerr << "Stereo buffer requested: "
01735               << (glWidget_->format().stereo() ? "ok\n" : "failed\n");
01736 
01737 
01738   // toolbar
01739   buttonBar_= new QToolBar( "Viewer Toolbar", work );
01740   buttonBar_->setOrientation(Qt::Vertical);
01741 
01742   moveButton_ = new QToolButton( buttonBar_ );
01743   moveButton_->setIcon( QPixmap(moveIcon) );
01744   moveButton_->setMinimumSize( 16, 16 );
01745   moveButton_->setMaximumSize( 32, 32 );
01746   moveButton_->setToolTip( "Switch to <b>move</b> mode." );
01747   moveButton_->setWhatsThis(
01748                   "Switch to <b>move</b> mode.<br>"
01749                   "<ul><li><b>Rotate</b> using <b>left</b> mouse button.</li>"
01750                   "<li><b>Translate</b> using <b>middle</b> mouse button.</li>"
01751                   "<li><b>Zoom</b> using <b>left+middle</b> mouse buttons.</li></ul>" );
01752   QObject::connect( moveButton_, SIGNAL( clicked() ),
01753                     this,        SLOT( examineMode() ) );
01754 
01755   buttonBar_->addWidget( moveButton_)->setText("Move");
01756 
01757   lightButton_ = new QToolButton( buttonBar_ );
01758   lightButton_->setIcon( QPixmap(lightIcon) );
01759   lightButton_->setMinimumSize( 16, 16 );
01760   lightButton_->setMaximumSize( 32, 32 );
01761   lightButton_->setToolTip("Switch to <b>light</b> mode.");
01762   lightButton_->setWhatsThis(
01763                   "Switch to <b>light</b> mode.<br>"
01764                   "Rotate lights using left mouse button.");
01765   QObject::connect( lightButton_, SIGNAL( clicked() ),
01766                     this,         SLOT( lightMode() ) );
01767   buttonBar_->addWidget( lightButton_)->setText("Light");
01768 
01769 
01770   pickButton_ = new QToolButton( buttonBar_ );
01771   pickButton_->setIcon( QPixmap(pickIcon) );
01772   pickButton_->setMinimumSize( 16, 16 );
01773   pickButton_->setMaximumSize( 32, 32 );
01774   pickButton_->setToolTip("Switch to <b>picking</b> mode.");
01775   pickButton_->setWhatsThis(
01776                   "Switch to <b>picking</b> mode.<br>"
01777                   "Use picking functions like flipping edges.<br>"
01778                   "To change the mode use the right click<br>"
01779                   "context menu in the viewer.");
01780   QObject::connect( pickButton_, SIGNAL( clicked() ),
01781                     this,        SLOT( pickingMode() ) );
01782   buttonBar_->addWidget( pickButton_)->setText("Pick");
01783 
01784 
01785   questionButton_ = new QToolButton( buttonBar_ );
01786   questionButton_->setIcon( QPixmap(questionIcon) );
01787   questionButton_->setMinimumSize( 16, 16 );
01788   questionButton_->setMaximumSize( 32, 32 );
01789   questionButton_->setToolTip("Switch to <b>identification</b> mode.");
01790   questionButton_->setWhatsThis(
01791                   "Switch to <b>identification</b> mode.<br>"
01792                   "Use identification mode to get information "
01793                   "about objects. Click on an object and see "
01794                   "the log output for information about the "
01795                   "object.");
01796   QObject::connect( questionButton_, SIGNAL( clicked() ),
01797                     this,            SLOT( questionMode() ) );
01798   buttonBar_->addWidget( questionButton_)->setText("Question");
01799 
01800   buttonBar_->addSeparator();
01801 
01802   homeButton_ = new QToolButton( buttonBar_ );
01803   homeButton_->setIcon( QPixmap(homeIcon) );
01804   homeButton_->setMinimumSize( 16, 16 );
01805   homeButton_->setMaximumSize( 32, 32 );
01806   homeButton_->setCheckable( false );
01807   homeButton_->setToolTip("Restore <b>home</b> view.");
01808   homeButton_->setWhatsThis(
01809                   "Restore home view<br><br>"
01810                   "Resets the view to the home view");
01811   QObject::connect( homeButton_, SIGNAL( clicked() ),
01812                     this,        SLOT( home() ) );
01813   buttonBar_->addWidget( homeButton_)->setText("Home");
01814 
01815 
01816   setHomeButton_ = new QToolButton( buttonBar_ );
01817   setHomeButton_->setIcon( QPixmap(sethomeIcon) );
01818   setHomeButton_->setMinimumSize( 16, 16 );
01819   setHomeButton_->setMaximumSize( 32, 32 );
01820   setHomeButton_->setCheckable( false );
01821   setHomeButton_->setToolTip("Set <b>home</b> view");
01822   setHomeButton_->setWhatsThis(
01823                   "Store home view<br><br>"
01824                   "Stores the current view as the home view");
01825   QObject::connect( setHomeButton_, SIGNAL( clicked() ),
01826                     this,           SLOT( setHome() ) );
01827   buttonBar_->addWidget( setHomeButton_)->setText("Set Home");
01828 
01829 
01830   viewAllButton_ = new QToolButton( buttonBar_ );
01831   viewAllButton_->setIcon( QPixmap(viewallIcon) );
01832   viewAllButton_->setMinimumSize( 16, 16 );
01833   viewAllButton_->setMaximumSize( 32, 32 );
01834   viewAllButton_->setCheckable( false );
01835   viewAllButton_->setToolTip("View all.");
01836   viewAllButton_->setWhatsThis(
01837                   "View all<br><br>"
01838                   "Move the objects in the scene so that"
01839                   " the whole scene is visible.");
01840   QObject::connect( viewAllButton_, SIGNAL( clicked() ),
01841                     this,           SLOT( viewAll() ) );
01842   buttonBar_->addWidget( viewAllButton_)->setText("View all");
01843 
01844 
01845   projectionButton_ = new QToolButton( buttonBar_ );
01846   projectionButton_->setIcon( QPixmap(perspectiveIcon) );
01847   projectionButton_->setMinimumSize( 16, 16 );
01848   projectionButton_->setMaximumSize( 32, 32 );
01849   projectionButton_->setCheckable( false );
01850   projectionButton_->setToolTip(
01851                 "Switch between <b>perspective</b> and "
01852                 "<b>parrallel</b> projection mode.");
01853   projectionButton_->setWhatsThis(
01854                 "Switch projection modes<br><br>"
01855                 "Switch between <b>perspective</b> and "
01856                 "<b>parrallel</b> projection mode.");
01857   QObject::connect( projectionButton_, SIGNAL( clicked() ),
01858                     this,              SLOT( toggleProjectionMode() ) );
01859   buttonBar_->addWidget( projectionButton_)->setText( "Projection" );
01860 
01861 
01862   if (glWidget_->format().stereo())
01863   {
01864     stereoButton_ = new QToolButton( buttonBar_ );
01865     stereoButton_->setIcon( QPixmap(monoIcon) );
01866     stereoButton_->setMinimumSize( 16, 16 );
01867     stereoButton_->setMaximumSize( 32, 32 );
01868     stereoButton_->setCheckable( true );
01869     stereoButton_->setToolTip( "Toggle stereo viewing");
01870     stereoButton_->setWhatsThis(
01871                   "Toggle stereo mode<br><br>"
01872                   "Use this button to switch between stereo "
01873                   "and mono view. To use this feature you need "
01874                   "a stereo capable graphics card and a stereo "
01875                   "display/projection system.");
01876     QObject::connect( stereoButton_, SIGNAL( clicked() ),
01877                       this,          SLOT( toggleStereoMode() ) );
01878     buttonBar_->addWidget( stereoButton_)->setText( "Stereo");
01879   }
01880 
01881   buttonBar_->addSeparator();
01882 
01883   sceneGraphButton_ = new QToolButton( buttonBar_ );
01884   sceneGraphButton_->setIcon( QPixmap(sceneGraphIcon) );
01885   sceneGraphButton_->setMinimumSize( 16, 16 );
01886   sceneGraphButton_->setMaximumSize( 32, 32 );
01887   sceneGraphButton_->setCheckable( false );
01888   sceneGraphButton_->setToolTip("Toggle scene graph viewer.");
01889   sceneGraphButton_->setWhatsThis(
01890                   "Toggle scene graph viewer<br><br>"
01891                   "The scene graph viewer enables you to examine the "
01892                   "displayed scene graph and to modify certain nodes.<br><br>"
01893                   "There are three modi for the scene graph viewer:"
01894                   "<ul><li><b>hidden</b></li>"
01895                   "<li><b>split</b>: share space</li>"
01896                   "<li><b>dialog</b>: own dialog window</li></ul>"
01897                   "This button toggles between these modi.");
01898   QObject::connect( sceneGraphButton_, SIGNAL( clicked() ),
01899                     this,              SLOT( showSceneGraphDialog() ) );
01900   buttonBar_->addWidget( sceneGraphButton_)->setText( "SceneGraph" );
01901 
01902   glLayout_ = new QGridLayout(work);
01903   glLayout_->setSpacing( 0 );
01904   glLayout_->setMargin( 0 );
01905 
01906   glLayout_->addWidget(glView_,    0,0);
01907   glLayout_->addWidget(buttonBar_, 0,1);
01908 
01909   glLayout_->setColumnStretch(0,1);
01910   glLayout_->setColumnStretch(1,0);
01911 
01912   if (!(options_ & ShowToolBar))
01913     buttonBar_->hide();
01914 
01915 }
01916 
01917 
01918 //-----------------------------------------------------------------------------
01919 
01920 
01921 void QtBaseViewer::updatePopupMenu()
01922 {
01923   //
01924   // Draw mode menu
01925   //
01926 
01927   if ( ! drawMenu_ )
01928   {
01929     drawMenu_ = new QMenu( this );
01930     connect( drawMenu_, SIGNAL( aboutToHide() ),
01931              this, SLOT( hidePopupMenus() ) );
01932 
01933   }
01934 
01935   QActionGroup * drawGroup = new QActionGroup( this );
01936   drawGroup->setExclusive( false );
01937   connect( drawGroup, SIGNAL( triggered( QAction * ) ),
01938            this, SLOT( actionDrawMenu( QAction * ) ) );
01939 
01940 
01941 
01942   drawMenuActions_.clear();
01943 
01944   std::vector< unsigned int > draw_mode_id;
01945 
01946   draw_mode_id = SceneGraph::DrawModes::getDrawModeIDs( availDrawModes_ );
01947 
01948   for ( unsigned int i = 0; i < draw_mode_id.size(); ++i )
01949   {
01950     unsigned int id    = draw_mode_id[i];
01951     std::string  descr = SceneGraph::DrawModes::description( id );
01952 
01953     QAction * action = new QAction( descr.c_str(), drawGroup );
01954     action->setData( QVariant( id ) );
01955     action->setCheckable( true );
01956     action->setChecked( SceneGraph::DrawModes::containsId( curDrawMode_, id ) );
01957     drawMenuActions_.push_back( action );
01958   }
01959 
01960 
01961   drawMenu_->clear();
01962   drawMenu_->addActions( drawGroup->actions() );
01963 
01964 
01965   // function menu
01966 
01967   if (!funcMenu_)
01968   {
01969     funcMenu_=new QMenu( this );
01970 
01971     funcMenu_->addAction( action_[ "Background" ] );
01972     funcMenu_->addSeparator();
01973     funcMenu_->addAction( action_[ "Snapshot" ] );
01974     funcMenu_->addAction( action_[ "SnapshotName" ] );
01975     funcMenu_->addAction( action_[ "SnapshotSavesView" ] );
01976     funcMenu_->addSeparator();
01977     funcMenu_->addAction( action_[ "CopyView" ] );
01978     funcMenu_->addAction( action_[ "PasteView" ] );
01979     funcMenu_->addAction( action_[ "PasteDropSize" ] );
01980     funcMenu_->addSeparator();
01981     funcMenu_->addAction( action_[ "Synchronize" ] );
01982     funcMenu_->addSeparator();
01983     funcMenu_->addAction( action_[ "Animation" ] );
01984     funcMenu_->addAction( action_[ "BackfaceCulling" ] );
01985     funcMenu_->addAction( action_[ "TwoSidedLighting" ] );
01986 
01987     connect( funcMenu_, SIGNAL( aboutToHide() ),
01988              this, SLOT( hidePopupMenus() ) );
01989   }
01990 
01991 
01992 }
01993 
01994 
01995 //-----------------------------------------------------------------------------
01996 
01997 
01998 void QtBaseViewer::hidePopupMenus()
01999 {
02000   if ( drawMenu_ )
02001   {
02002     drawMenu_->blockSignals(true);
02003     drawMenu_->hide();
02004     drawMenu_->blockSignals(false);
02005   }
02006 
02007   if ( funcMenu_ )
02008   {
02009     funcMenu_->blockSignals(true);
02010     funcMenu_->hide();
02011     funcMenu_->blockSignals(false);
02012   }
02013 
02014   if ( pickMenu_ )
02015   {
02016     pickMenu_->blockSignals(true);
02017     pickMenu_->hide();
02018     pickMenu_->blockSignals(false);
02019   }
02020 }
02021 
02022 
02023 //-----------------------------------------------------------------------------
02024 
02025 
02026 void QtBaseViewer::translate(const Vec3d& _trans)
02027 {
02028   makeCurrent();
02029   glstate_->translate(_trans[0], _trans[1], _trans[2], MULT_FROM_LEFT);
02030 }
02031 
02032 
02033 //-----------------------------------------------------------------------------
02034 
02035 
02036 void QtBaseViewer::initModelviewMatrix()
02037 {
02038   makeCurrent();
02039   glstate_->reset_modelview();
02040 }
02041 
02042 
02043 //-----------------------------------------------------------------------------
02044 
02045 
02046 void QtBaseViewer::rotate(const Vec3d&  _axis,
02047                           double        _angle,
02048                           const Vec3d&  _center)
02049 {
02050   makeCurrent();
02051   Vec3d t = glstate_->modelview().transform_point(_center);
02052   glstate_->translate(-t[0], -t[1], -t[2], MULT_FROM_LEFT);
02053   glstate_->rotate(_angle, _axis[0], _axis[1], _axis[2], MULT_FROM_LEFT);
02054   glstate_->translate( t[0],  t[1],  t[2], MULT_FROM_LEFT);
02055 
02056   sync_send( glstate_->modelview(), glstate_->inverse_modelview() );
02057 }
02058 
02059 
02060 //-----------------------------------------------------------------------------
02061 
02062 
02063 unsigned int QtBaseViewer::glWidth() const {
02064   return glView_->width();
02065 }
02066 unsigned int QtBaseViewer::glHeight() const {
02067   return glView_->height();
02068 }
02069 QSize QtBaseViewer::glSize() const {
02070   return glView_->size();
02071 }
02072 QPoint QtBaseViewer::glMapFromGlobal( const QPoint& _pos ) const {
02073   return glView_->mapFromGlobal(_pos);
02074 }
02075 
02076 QPoint QtBaseViewer::glMapToGlobal( const QPoint& _pos ) const {
02077   return glView_->mapToGlobal(_pos);
02078 }
02079 
02080 
02081 //-----------------------------------------------------------------------------
02082 
02083 
02084 void
02085 QtBaseViewer::showSceneGraphDialog()
02086 {
02087   if (sceneGraphRoot_)
02088   {
02089     if (!sceneGraphDialog_)
02090     {
02091       sceneGraphDialog_ = new QtSceneGraphDialog( this, sceneGraphRoot_ );
02092 
02093       connect(this,
02094               SIGNAL(signalSceneGraphChanged(ACG::SceneGraph::BaseNode*)),
02095               sceneGraphDialog_,
02096               SLOT(update(ACG::SceneGraph::BaseNode*)));
02097 
02098       connect(sceneGraphDialog_,
02099               SIGNAL(signalNodeChanged(ACG::SceneGraph::BaseNode*)),
02100               this,
02101               SLOT(slotNodeChanged(ACG::SceneGraph::BaseNode*)));
02102     }
02103 
02104     sceneGraphDialog_->show();
02105   }
02106 }
02107 
02108 
02109 //-----------------------------------------------------------------------------
02110 
02111 
02112 void
02113 QtBaseViewer::slotNodeChanged(ACG::SceneGraph::BaseNode* _node)
02114 {
02115   emit(signalNodeChanged(_node));
02116   updateGL();
02117 }
02118 
02119 
02120 //-----------------------------------------------------------------------------
02121 
02122 
02123 void QtBaseViewer::slotWheelX(double _dAngle)
02124 {
02125   rotate(Vec3d(1,0,0),QtWheel::deg(QtWheel::clip(_dAngle)));
02126   updateGL();
02127 
02128   // sync
02129   emit(signalSetView(glstate_->modelview(), glstate_->inverse_modelview()));
02130   
02131   emit viewChanged();
02132 }
02133 
02134 void QtBaseViewer::slotWheelY(double _dAngle)
02135 {
02136   rotate(Vec3d(0,1,0),QtWheel::deg(QtWheel::clip(_dAngle)));
02137   updateGL();
02138 
02139   // sync
02140   emit(signalSetView(glstate_->modelview(), glstate_->inverse_modelview()));
02141   
02142   emit viewChanged();
02143 }
02144 
02145 void QtBaseViewer::slotWheelZ(double _dist)
02146 {
02147   double dz=_dist*0.5/M_PI*scene_radius_*2.0;
02148   translate(Vec3d(0,0,dz));
02149   updateGL();
02150 
02151   // sync
02152   emit(signalSetView(glstate_->modelview(), glstate_->inverse_modelview()));
02153   
02154   emit viewChanged();
02155 }
02156 
02157 
02158 //-----------------------------------------------------------------------------
02159 
02160 void QtBaseViewer::sceneRectChanged(const QRectF &rect)
02161 {
02162   glBase_->setGeometry (rect);
02163 }
02164 
02165 //-----------------------------------------------------------------------------
02166 
02167 
02168 void QtBaseViewer::grabGLArea()
02169 {
02170   glareaGrabbed_ = true;
02171 
02172   glView_->setCursor(Qt::BlankCursor);
02173   glBase_->setCursor(Qt::BlankCursor);
02174   glView_->grabMouse();
02175   glView_->grabKeyboard();
02176 }
02177 
02178 void QtBaseViewer::releaseGLArea()
02179 {
02180   glareaGrabbed_ = false;
02181 
02182   glView_->releaseMouse();
02183   glView_->releaseKeyboard();
02184   glView_->setCursor(Qt::ArrowCursor);
02185   glBase_->setCursor(Qt::ArrowCursor);
02186 }
02187 
02188 
02189 //-----------------------------------------------------------------------------
02190 
02191 
02192 void QtBaseViewer::glContextMenuEvent(QContextMenuEvent* _event)
02193 {
02194 
02195   if (popupEnabled_)
02196   {
02197     QPoint  cpos(QCursor::pos()), dpos, fpos, ppos;
02198     int     offset = 10, dw, dh, fw, fh, pw, ph;
02199     int     minx, maxx, miny, maxy;
02200     int     dx(0), dy(0);
02201 
02202 
02203 #ifdef ARCH_DARWIN
02204 #  define WIDTH  width()
02205 #  define HEIGHT height()
02206 #else
02207 #  define WIDTH  sizeHint().width()
02208 #  define HEIGHT sizeHint().height()
02209 #endif
02210 
02211 
02212 
02213     // drawing mode menu
02214     if (drawMenu_)//TODO: && drawMenu_->count()>0)
02215     {
02216       dw = drawMenu_->WIDTH;
02217       dh = drawMenu_->HEIGHT;
02218       dpos = cpos + QPoint(offset, offset);
02219     }
02220     else
02221     {
02222       dpos = cpos; dw=dh=0;
02223     }
02224 
02225 
02226     // function menu
02228     if (funcMenu_)
02229     {
02230       fw = funcMenu_->WIDTH;
02231       fh = funcMenu_->HEIGHT;
02232       fpos = cpos + QPoint(offset, -offset-fh);
02233     }
02234     else
02235     {
02236       fpos = cpos; fw=fh=0;
02237     }
02238 
02239 
02240     // pick mode menu
02242     if (pickMenu_)
02243     {
02244       pw = pickMenu_->WIDTH;
02245       ph = pickMenu_->HEIGHT;
02246       ppos = cpos + QPoint(-offset-pw, -ph/2);
02247     }
02248     else
02249     {
02250       ppos = cpos; pw=ph=0;
02251     }
02252 
02253 
02254 
02255     // handle screen boundaries
02256     minx = std::min(dpos.x(),    std::min(fpos.x(),    ppos.x()));
02257     maxx = std::max(dpos.x()+dw, std::max(fpos.x()+fw, ppos.x()+pw));
02258     miny = std::min(dpos.y(),    std::min(fpos.y(),    ppos.y()));
02259     maxy = std::max(dpos.y()+dh, std::max(fpos.y()+fh, ppos.y()+ph));
02260 
02261 
02262     if (minx < 0)
02263     {
02264       dx = -minx;
02265     }
02266     else if (maxx >= qApp->desktop()->width())
02267     {
02268       dx = qApp->desktop()->width() - maxx;
02269     }
02270 
02271     if (miny < 0)
02272     {
02273       dy = -miny;
02274     }
02275     else if (maxy >= qApp->desktop()->height())
02276     {
02277       dy = qApp->desktop()->height() - maxy;
02278     }
02279 
02280 
02281     dpos += QPoint(dx, dy);
02282     fpos += QPoint(dx, dy);
02283     ppos += QPoint(dx, dy);
02284 
02285 
02286 
02287     // popping up 3 menus only works w/o Qt menu fade/animate effects
02288     bool animate_menu = qApp->isEffectEnabled(Qt::UI_AnimateMenu);
02289     bool fade_menu    = qApp->isEffectEnabled(Qt::UI_FadeMenu);
02290     if (animate_menu)  qApp->setEffectEnabled(Qt::UI_AnimateMenu, false);
02291     if (fade_menu)     qApp->setEffectEnabled(Qt::UI_FadeMenu, false);
02292 
02293 
02294     // popup the 3 menus
02295 
02296     if (drawMenu_) 
02297     {
02298       //      SceneGraph::DrawModes::setQPopupMenuChecked(drawMenu_, curDrawMode_);
02299       drawMenu_->popup(dpos);
02300     }
02301 
02302     if (funcMenu_) 
02303       funcMenu_->popup(fpos);
02304 
02305     if (pickMenu_) 
02306       pickMenu_->popup(ppos);
02307 
02308 
02309     // restore effect state
02310     if (animate_menu)  qApp->setEffectEnabled(Qt::UI_AnimateMenu, true);
02311     if (fade_menu)     qApp->setEffectEnabled(Qt::UI_FadeMenu, true);
02312 
02313 
02314     _event->accept();
02315   }
02316 }
02317 
02318 
02319 //-----------------------------------------------------------------------------
02320 
02321 
02322 void QtBaseViewer::glMousePressEvent(QMouseEvent* _event)
02323 {
02324   // right button pressed => popup menu (ignore here)
02325   if (_event->button() == Qt::RightButton && popupEnabled_)
02326   {
02327     return;
02328   }
02329   else
02330   {
02331     switch (actionMode_)
02332     {
02333       case ExamineMode:
02334         if ((_event->modifiers() & Qt::ControlModifier)) // drag&drop
02335           if ( externalDrag_ ) {
02336             emit startDragEvent( _event );
02337           } else {
02338             startDrag();
02339           }
02340         else
02341           viewMouseEvent(_event); // examine
02342         break;
02343 
02344       case LightMode:
02345         lightMouseEvent(_event);
02346         break;
02347 
02348       case PickingMode: // give event to application
02349         emit(signalMouseEvent(_event, pick_mode_name_));
02350         emit(signalMouseEvent(_event));
02351         break;
02352 
02353       case QuestionMode: // give event to application
02354         emit(signalMouseEventIdentify(_event));
02355         break;
02356     }
02357   }
02358 }
02359 
02360 
02361 //-----------------------------------------------------------------------------
02362 
02363 
02364 void QtBaseViewer::glMouseDoubleClickEvent(QMouseEvent* _event)
02365 {
02366   switch (actionMode_)
02367   {
02368     case ExamineMode:
02369       viewMouseEvent(_event);
02370       break;
02371 
02372     case LightMode:
02373       lightMouseEvent(_event);
02374       break;
02375 
02376     case PickingMode: // give event to application
02377       emit(signalMouseEvent(_event, pick_mode_name_));
02378       emit(signalMouseEvent(_event));
02379       break;
02380 
02381     case QuestionMode: // give event to application
02382       emit(signalMouseEventIdentify(_event));
02383       break;
02384   }
02385 }
02386 
02387 
02388 //-----------------------------------------------------------------------------
02389 
02390 
02391 void QtBaseViewer::glMouseMoveEvent(QMouseEvent* _event)
02392 {
02393   switch ( actionMode_ )
02394   {
02395     case ExamineMode:
02396       viewMouseEvent(_event);
02397       break;
02398 
02399     case LightMode:
02400       lightMouseEvent(_event);
02401       break;
02402 
02403     case PickingMode:
02404       // give event to application
02405       // deliver mouse moves with no button down, if tracking is enabled,
02406       if ((_event->buttons() & (Qt::LeftButton | Qt::MidButton | Qt::RightButton))
02407           || trackMouse_)
02408       {
02409         emit(signalMouseEvent(_event, pick_mode_name_));
02410         emit(signalMouseEvent(_event));
02411       }
02412       break;
02413 
02414     case QuestionMode: // give event to application
02415       emit(signalMouseEventIdentify(_event));
02416       break;
02417 
02418     default: // avoid warning
02419       break;
02420   }
02421 }
02422 
02423 
02424 //-----------------------------------------------------------------------------
02425 
02426 
02427 void QtBaseViewer::glMouseReleaseEvent(QMouseEvent* _event)
02428 {
02429 //   if (_event->button() == Qt::RightButton )
02430 //     hidePopupMenus();
02431 
02432   if (_event->button() != Qt::RightButton ||
02433       (actionMode_ == PickingMode && !popupEnabled_) )
02434   {
02435     switch ( actionMode_ )
02436     {
02437       case ExamineMode:
02438         viewMouseEvent(_event);
02439         break;
02440 
02441       case LightMode:
02442         lightMouseEvent(_event);
02443         break;
02444 
02445       case PickingMode: // give event to application
02446         emit(signalMouseEvent(_event, pick_mode_name_));
02447         emit(signalMouseEvent(_event));
02448         break;
02449 
02450       case QuestionMode: // give event to application
02451         emit(signalMouseEventIdentify(_event));
02452         break;
02453 
02454       default: // avoid warning
02455         break;
02456     }
02457   }
02458 
02459   isRotating_ = false;
02460 }
02461 
02462 
02463 //-----------------------------------------------------------------------------
02464 
02465 
02466 void QtBaseViewer::glMouseWheelEvent(QWheelEvent* _event)
02467 {
02468   switch ( actionMode_ )
02469   {
02470     case ExamineMode:
02471       viewWheelEvent(_event);
02472       break;
02473 
02474     case PickingMode: // give event to application
02475       emit(signalWheelEvent(_event, pick_mode_name_));
02476       break;
02477 
02478     default: // avoid warning
02479       break;
02480   }
02481 
02482   isRotating_ = false;
02483 }
02484 
02485 //-----------------------------------------------------------------------------
02486 
02487 
02488 void QtBaseViewer::updatePickMenu()
02489 {
02490   delete pickMenu_;
02491 
02492   pickMenu_ = new QMenu( 0 );
02493   connect( pickMenu_, SIGNAL( aboutToHide() ),
02494            this, SLOT( hidePopupMenus() ) );
02495 
02496   QActionGroup * ag = new QActionGroup( pickMenu_ );
02497   ag->setExclusive( true );
02498 
02499   for (unsigned int i=0; i<pick_modes_.size(); ++i) {
02500     if ( !pick_modes_[i].visible )
02501       continue;
02502 
02503     if (pick_modes_[i].name == "Separator")
02504     {
02505       if ((i > 0) && (i<pick_modes_.size()-1)) // not first, not last
02506            pickMenu_->addSeparator();
02507     }
02508     else
02509     {
02510       QAction * ac = new QAction( pick_modes_[i].name.c_str(), ag );
02511       ac->setData( QVariant( i ) );
02512       ac->setCheckable( true );
02513 
02514       if ((int)i == pick_mode_idx_)
02515         ac->setChecked( true );
02516 
02517       pickMenu_->addAction( ac );
02518     }
02519   }
02520 
02521   connect( ag, SIGNAL( triggered( QAction * ) ),
02522            this, SLOT( actionPickMenu( QAction * ) ));
02523 }
02524 
02525 //-----------------------------------------------------------------------------
02526 
02527 
02528 void QtBaseViewer::actionPickMenu( QAction * _action )
02529 {
02530   int _id = _action->data().toInt();
02531   if (_id < (int) pick_modes_.size() )
02532   {
02533     pickMode( _id );
02534   }
02535 
02536   actionMode( PickingMode );
02537 
02538   hidePopupMenus();
02539 }
02540 
02541 //-----------------------------------------------------------------------------
02542 
02543 QToolBar* QtBaseViewer::getToolBar() {
02544   return buttonBar_;
02545 }
02546 
02547 QToolBar* QtBaseViewer::removeToolBar() {
02548   glLayout_->removeWidget( buttonBar_ );
02549   return buttonBar_;
02550 }
02551 
02552 //-----------------------------------------------------------------------------
02553 
02554 
02555 void QtBaseViewer::moveForward() {
02556   if(navigationMode_ ==  FIRSTPERSON_NAVIGATION) {
02557     
02558     ACG::Vec3d dir = glstate_->viewing_direction();
02559     
02560     dir *= -0.1;
02561     
02562     glstate_->translate(dir[0], dir[1], dir[2]);
02563     
02564     updateGL();
02565     
02566     emit viewChanged();
02567   }
02568 }
02569 
02570 void QtBaseViewer::moveBack() {
02571   if(navigationMode_ ==  FIRSTPERSON_NAVIGATION) {
02572     ACG::Vec3d dir = glstate_->viewing_direction();
02573     
02574     dir *= 0.1;
02575     
02576     glstate_->translate(dir[0], dir[1], dir[2]);
02577     
02578     updateGL();
02579     
02580     emit viewChanged();
02581   }
02582 }
02583 
02584 void QtBaseViewer::strafeLeft() {
02585   if(navigationMode_ ==  FIRSTPERSON_NAVIGATION) {
02586     ACG::Vec3d dir = glstate_->right();
02587     
02588     dir *= 0.1;
02589     
02590     glstate_->translate(dir[0], dir[1], dir[2]);
02591     
02592     updateGL();
02593     
02594     emit viewChanged();
02595   }
02596 }
02597 
02598 void QtBaseViewer::strafeRight() {
02599   if(navigationMode_ ==  FIRSTPERSON_NAVIGATION) {
02600     ACG::Vec3d dir = glstate_->right();
02601     
02602     dir *= -0.1;
02603     
02604     glstate_->translate(dir[0], dir[1], dir[2]);
02605     
02606     updateGL();
02607     
02608     emit viewChanged();
02609   }
02610 }
02611 
02612 //=============================================================================
02613 } // namespace QtWidgets
02614 } // namespace ACG
02615 //=============================================================================

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