00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
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
00139
00140 namespace ACG {
00141 namespace QtWidgets {
00142
00143
00144
00145
00146 static const char VIEW_MAGIC[] =
00147 "ACG::QtWidgets::QGLViewerWidget encoded view";
00148
00149
00150
00151
00152 QtBaseViewer::QtBaseViewer( QWidget* _parent,
00153 const char* ,
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
00179 if ( !QGLFormat::hasOpenGL() )
00180 {
00181 std::cerr << "This system has no OpenGL support.\n";
00182 exit(1);
00183 }
00184
00185
00186
00187 createWidgets(_format,_statusBar,_share);
00188
00189
00190
00191 glstate_ = new GLState();
00192
00193
00194
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
00228 stereo_ = false;
00229
00230
00231 pickMenu_ = 0;
00232 funcMenu_ = 0;
00233 drawMenu_ = 0;
00234
00235
00236
00237 actionMode_ = PickingMode;
00238 lastActionMode_ = PickingMode;
00239 examineMode();
00240
00241
00242
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
00260
00261
00262
00263
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
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
00412 SceneGraph::CollectDrawModesAction action;
00413 SceneGraph::traverse(sceneGraphRoot_, action);
00414 availDrawModes_ = action.drawModes();
00415 updatePopupMenu();
00416
00417
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
00446 }
00447
00448
00449 void QtBaseViewer::unlockUpdate()
00450 {
00451
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
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
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
00603 far_ = std::max(0.0002f * scene_radius_, -(c[2] - scene_radius_));
00604
00605
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
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
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 , unsigned int ,
00796 unsigned int , unsigned int ,
00797 GLenum )
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
00836
00837
00838 ACG::Vec3d c = glstate_->modelview().transform_point(scene_center_);
00839
00840
00841 far_ = std::max(0.0002f * scene_radius_, -(c[2] - scene_radius_));
00842
00843
00844 near_ = std::max(0.0001f * scene_radius_, -(c[2] + scene_radius_));
00845
00846
00847 updateProjectionMatrix();
00848
00849
00850 glstate_->set_msSinceLastRedraw (redrawTime_.restart ());
00851
00852
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
00884 makeCurrent();
00885
00886 glDisable(GL_LIGHTING);
00887 glClear(GL_DEPTH_BUFFER_BIT);
00888 glInitNames();
00889 glPushName((GLuint) 0);
00890
00891
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
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
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
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
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
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
01028 orthoWidth_ *= _move_back ? 2.0 : 0.5;
01029
01030
01031
01032 trackball_center_ = hitPoint;
01033
01035
01036
01037 updateProjectionMatrix();
01038
01039
01040 updateGL();
01041 }
01042
01043
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
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
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
01080 unsigned int frames = (unsigned int)(_time / frame_time_);
01081 if (frames > 1000) frames=1000;
01082
01083
01084
01085
01086
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
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
01138
01139 glewInit();
01140
01141
01142
01143 lockUpdate();
01144
01145
01146 glstate_->initialize();
01147
01148
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
01163 light_matrix_.identity();
01164 update_lights();
01165
01166
01167
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
01174 glstate_->translate(0.0, 0.0, -3.0);
01175 setHome();
01176
01177
01178
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
01190 emit(signalInitializeGL());
01191
01192
01193
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
01250
01251 glewInit();
01252
01253
01254 lockUpdate();
01255
01256
01257 glstate_->initialize();
01258
01259
01260 light_matrix_.identity();
01261
01262
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
01268 glstate_->translate(0.0, 0.0, -3.0);
01269 setHome();
01270
01271
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
01282 emit(signalInitializeGL());
01283
01284
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
01313 update_lights();
01314
01315 glstate_->setState ();
01316
01317 glColor4f(1.0,0.0,0.0,1.0);
01318
01319
01320 if (!stereo_)
01321 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01322
01323 unlockUpdate();
01324
01325
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
01354 const ACG::GLMatrixd m = glstate_->modelview();
01355 const ACG::GLMatrixd p = glstate_->projection();
01356
01357
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
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
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
01384 QString temp = _view;
01385 temp.remove(0,sizeof(VIEW_MAGIC));
01386
01387
01388 QStringList split = temp.split(QRegExp("[\\n\\s]"),QString::SkipEmptyParts);
01389
01390 ACG::GLMatrixd m, p;
01391 int w, h, pMode;
01392
01393
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
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
01441 makeCurrent();
01442
01443
01444 if (projectionMode_ != (ProjectionMode)pMode)
01445 projectionMode((ProjectionMode)pMode);
01446
01447
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
01475 if (qApp->keyboardModifiers() & Qt::ShiftModifier)
01476 {
01477 if (drawMode() & mode)
01478 drawMode(drawMode() & ~mode);
01479 else
01480 drawMode(drawMode() | mode);
01481 }
01482
01483
01484 else
01485 {
01486
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
01625
01626 QVBoxLayout* layout=new QVBoxLayout(this);
01627 layout->setSpacing( 0 );
01628 layout->setMargin( 0 );
01629
01630
01631
01632
01633 QFrame* work=new QFrame(this);
01634
01635 layout->addWidget(work,1);
01636
01637
01638
01639 assert(statusbar_!=0);
01640 if (privateStatusBar_!=0)
01641 layout->addWidget(privateStatusBar_,0);
01642
01643
01644
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
01727
01728
01729 connect( glView_ , SIGNAL( customContextMenuRequested( const QPoint& ) ) ,
01730 this , SIGNAL( signalCustomContextMenuRequested( const QPoint& ) ) );
01731
01732
01733 if (format.stereo())
01734 std::cerr << "Stereo buffer requested: "
01735 << (glWidget_->format().stereo() ? "ok\n" : "failed\n");
01736
01737
01738
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
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
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
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
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
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
02214 if (drawMenu_)
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
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
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
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
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
02295
02296 if (drawMenu_)
02297 {
02298
02299 drawMenu_->popup(dpos);
02300 }
02301
02302 if (funcMenu_)
02303 funcMenu_->popup(fpos);
02304
02305 if (pickMenu_)
02306 pickMenu_->popup(ppos);
02307
02308
02309
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
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))
02335 if ( externalDrag_ ) {
02336 emit startDragEvent( _event );
02337 } else {
02338 startDrag();
02339 }
02340 else
02341 viewMouseEvent(_event);
02342 break;
02343
02344 case LightMode:
02345 lightMouseEvent(_event);
02346 break;
02347
02348 case PickingMode:
02349 emit(signalMouseEvent(_event, pick_mode_name_));
02350 emit(signalMouseEvent(_event));
02351 break;
02352
02353 case QuestionMode:
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:
02377 emit(signalMouseEvent(_event, pick_mode_name_));
02378 emit(signalMouseEvent(_event));
02379 break;
02380
02381 case QuestionMode:
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
02405
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:
02415 emit(signalMouseEventIdentify(_event));
02416 break;
02417
02418 default:
02419 break;
02420 }
02421 }
02422
02423
02424
02425
02426
02427 void QtBaseViewer::glMouseReleaseEvent(QMouseEvent* _event)
02428 {
02429
02430
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:
02446 emit(signalMouseEvent(_event, pick_mode_name_));
02447 emit(signalMouseEvent(_event));
02448 break;
02449
02450 case QuestionMode:
02451 emit(signalMouseEventIdentify(_event));
02452 break;
02453
02454 default:
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:
02475 emit(signalWheelEvent(_event, pick_mode_name_));
02476 break;
02477
02478 default:
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))
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 }
02614 }
02615