QtExaminerViewer.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: 6743 $                                                       *
00038  *   $Author: moebius $                                                      *
00039  *   $Date: 2009-08-05 11:03:10 +0200 (Mi, 05. Aug 2009) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 
00044 
00045 //=============================================================================
00046 //
00047 //  CLASS QtExaminerViewer - IMPLEMENTATION
00048 //
00049 //=============================================================================
00050 
00051 
00052 //== INCLUDES =================================================================
00053 
00054 #include "QtExaminerViewer.hh"
00055 
00056 #include <QTimer>
00057 #include <QPushButton>
00058 #include <QClipboard>
00059 #include <QApplication>
00060 #include <QInputDialog>
00061 #include <QStatusBar>
00062 
00063 #include <QMouseEvent>
00064 #include <QWheelEvent>
00065 #include <QEvent>
00066 
00067 #ifdef max
00068 #  undef max
00069 #endif
00070 
00071 
00072 //== NAMESPACES ===============================================================
00073 
00074 
00075 namespace ACG {
00076 namespace QtWidgets {
00077 
00078 
00079 //== IMPLEMENTATION ==========================================================
00080 
00081 
00082 QtExaminerViewer::QtExaminerViewer( QWidget* _parent,
00083                                     const char* _name,
00084                                     QStatusBar *_statusBar,
00085                                     const QGLFormat* _format,
00086                                     const QtBaseViewer* _share,
00087                                     Options _options ) :
00088   QtBaseViewer(_parent, _name, _statusBar, _format, _share, _options)
00089 {
00090 
00091   // timer for animation
00092   timer_ = new QTimer( this );
00093   connect( timer_, SIGNAL(timeout()), this, SLOT( slotAnimation()) );
00094 
00095   allowRotation_ = true;
00096 
00097   //default wheel zoom factors
00098   wZoomFactor_ = 1.0;
00099   wZoomFactorShift_ = 0.2;
00100 }
00101 
00102 
00103 //-----------------------------------------------------------------------------
00104 
00105 
00106 void
00107 QtExaminerViewer::viewMouseEvent(QMouseEvent* _event)
00108 {
00109   switch (_event->type())
00110   {
00111     case QEvent::MouseButtonPress:
00112     {
00113       // shift key -> set rotation center
00114       if (_event->modifiers() & Qt::ShiftModifier)
00115       {
00116         Vec3d c;
00117         if (fast_pick(_event->pos(), c))
00118         {
00119           trackball_center_ = c;
00120           trackball_radius_ = std::max(scene_radius_, (c-glState().eye()).norm()*0.9f);
00121         }
00122       }
00123 
00124       lastPoint_hitSphere_ = mapToSphere( lastPoint2D_=_event->pos(),
00125                                           lastPoint3D_ );
00126       isRotating_ = true;
00127       timer_->stop();
00128 
00129 
00130       break;
00131     }
00132 
00133 
00134     case QEvent::MouseButtonDblClick:
00135     {
00136       if (allowRotation_)
00137         flyTo(_event->pos(), _event->button()==Qt::MidButton);
00138       break;
00139     }
00140 
00141 
00142     case QEvent::MouseMove:
00143     {
00144       double factor  = 1.0;
00145 
00146       if (_event->modifiers() == Qt::ShiftModifier)
00147         factor = wZoomFactorShift_;
00148 
00149       // mouse button should be pressed
00150       if (_event->buttons() & (Qt::LeftButton | Qt::MidButton))
00151       {
00152              QPoint newPoint2D = _event->pos();
00153 
00154         if ( (newPoint2D.x()<0) || (newPoint2D.x() > (int)glWidth()) ||
00155              (newPoint2D.y()<0) || (newPoint2D.y() > (int)glHeight()) )
00156           return;
00157 
00158         double value_x, value_y;
00159         Vec3d  newPoint3D;
00160         bool   newPoint_hitSphere = mapToSphere( newPoint2D, newPoint3D );
00161 
00162         makeCurrent();
00163 
00164         // move in z direction
00165         if ( (_event->buttons() & Qt::LeftButton) &&
00166               (_event->buttons() & Qt::MidButton))
00167         {
00168           switch (projectionMode())
00169           {
00170             case PERSPECTIVE_PROJECTION:
00171             {
00172               value_y = scene_radius_ * ((newPoint2D.y() - lastPoint2D_.y())) * 3.0 / (double) glHeight();
00173               translate( Vec3d(0.0, 0.0, value_y * factor ) );
00174               updateGL();
00175               break;
00176             }
00177 
00178             case ORTHOGRAPHIC_PROJECTION:
00179             {
00180               value_y = ((newPoint2D.y() - lastPoint2D_.y())) * orthoWidth_ / (double) glHeight();
00181               orthoWidth_ -= value_y  * factor;
00182               updateProjectionMatrix();
00183               updateGL();
00184               break;
00185             }
00186           }
00187         }
00188 
00189         // move in x,y direction
00190         else if (_event->buttons() & Qt::MidButton)
00191         {
00192           value_x = scene_radius_ * ((newPoint2D.x() - lastPoint2D_.x())) * 2.0 / (double) glWidth();
00193           value_y = scene_radius_ * ((newPoint2D.y() - lastPoint2D_.y())) * 2.0 / (double) glHeight();
00194           translate( Vec3d(value_x  * factor , -value_y  * factor , 0.0) );
00195         }
00196 
00197         // rotate
00198         else if (allowRotation_ && (_event->buttons() & Qt::LeftButton) )
00199         {
00200           Vec3d axis(1.0,0.0,0.0);
00201           double angle(0.0);
00202 
00203           if ( lastPoint_hitSphere_ ) {
00204 
00205             if ( ( newPoint_hitSphere = mapToSphere( newPoint2D,
00206                                 newPoint3D ) ) ) {
00207               axis = lastPoint3D_ % newPoint3D;
00208               double cos_angle = ( lastPoint3D_ | newPoint3D );
00209               if ( fabs(cos_angle) < 1.0 ) {
00210                 angle = acos( cos_angle ) * 180.0 / M_PI  * factor ;
00211                 angle *= 2.0; // inventor rotation
00212               }
00213             }
00214 
00215             rotate(axis, angle);
00216 
00217           }
00218 
00219           lastRotationAxis_  = axis;
00220           lastRotationAngle_ = angle;
00221         }
00222 
00223         lastPoint2D_ = newPoint2D;
00224         lastPoint3D_ = newPoint3D;
00225         lastPoint_hitSphere_ = newPoint_hitSphere;
00226 
00227         updateGL();
00228         lastMoveTime_.restart();
00229       }
00230       break;
00231     }
00232 
00233 
00234 
00235     case QEvent::MouseButtonRelease:
00236     {
00237       lastPoint_hitSphere_ = false;
00238 
00239       // continue rotation ?
00240       if ( isRotating_ &&
00241            (_event->button() == Qt::LeftButton) &&
00242            (!(_event->buttons() & Qt::MidButton)) &&
00243            (lastMoveTime_.elapsed() < 10) &&
00244            animation() )
00245              timer_->start(0);
00246       break;
00247     }
00248 
00249     default: // avoid warning
00250       break;
00251   }
00252 
00253 
00254   // sync views
00255   emit(signalSetView(glstate_->modelview(), glstate_->inverse_modelview()));
00256 }
00257 
00258 
00259 //-----------------------------------------------------------------------------
00260 
00261 
00262 void
00263 QtExaminerViewer::lightMouseEvent(QMouseEvent* _event)
00264 {
00265   switch (_event->type())
00266   {
00267     case QEvent::MouseButtonPress:
00268     {
00269       lastPoint_hitSphere_ = mapToSphere( lastPoint2D_=_event->pos(),
00270                                           lastPoint3D_ );
00271       isRotating_ = true;
00272       timer_->stop();
00273       break;
00274     }
00275 
00276 
00277     case QEvent::MouseMove:
00278     {
00279       // rotate lights
00280       if (_event->buttons() & Qt::LeftButton)
00281       {
00282         QPoint newPoint2D = _event->pos();
00283 
00284         if ( (newPoint2D.x()<0) || (newPoint2D.x() > (int)glWidth()) ||
00285              (newPoint2D.y()<0) || (newPoint2D.y() > (int)glHeight()) )
00286           return;
00287 
00288 
00289         Vec3d  newPoint3D;
00290         bool   newPoint_hitSphere = mapToSphere( newPoint2D, newPoint3D );
00291 
00292         makeCurrent();
00293 
00294         Vec3d axis(1.0,0.0,0.0);
00295         double angle(0.0);
00296 
00297         if ( lastPoint_hitSphere_ )
00298         {
00299           if ( ( newPoint_hitSphere = mapToSphere( newPoint2D, newPoint3D ) ) )
00300           {
00301             axis = lastPoint3D_ % newPoint3D;
00302             double cos_angle = ( lastPoint3D_ | newPoint3D );
00303             if ( fabs(cos_angle) < 1.0 ) {
00304               angle = acos( cos_angle ) * 180.0 / M_PI;
00305               angle *= 2.0;
00306             }
00307           }
00308           rotate_lights(axis, angle);
00309         }
00310 
00311         lastPoint2D_ = newPoint2D;
00312         lastPoint3D_ = newPoint3D;
00313         lastPoint_hitSphere_ = newPoint_hitSphere;
00314 
00315         updateGL();
00316       }
00317       break;
00318     }
00319 
00320 
00321     default: // avoid warning
00322       break;
00323   }
00324 }
00325 
00326 
00327 //-----------------------------------------------------------------------------
00328 
00329 double QtExaminerViewer::wheelZoomFactor(){
00330   return wZoomFactor_;
00331 }
00332 
00333 //-----------------------------------------------------------------------------
00334 
00335 double QtExaminerViewer::wheelZoomFactorShift(){
00336   return wZoomFactorShift_;
00337 }
00338 
00339 //-----------------------------------------------------------------------------
00340 
00341 void QtExaminerViewer::setWheelZoomFactor(double _factor){
00342   wZoomFactor_ = _factor;
00343 }
00344 
00345 //-----------------------------------------------------------------------------
00346 
00347 void QtExaminerViewer::setWheelZoomFactorShift(double _factor){
00348   wZoomFactorShift_ = _factor;
00349 }
00350 
00351 //-----------------------------------------------------------------------------
00352 
00353 void QtExaminerViewer::viewWheelEvent( QWheelEvent* _event)
00354 {
00355   double factor = wZoomFactor_;
00356 
00357   if (_event->modifiers() == Qt::ShiftModifier)
00358     factor = wZoomFactorShift_;
00359 
00360   switch (projectionMode())
00361   {
00362     case PERSPECTIVE_PROJECTION:
00363     {
00364       double d = -(double)_event->delta() / 120.0 * 0.2 * factor * trackball_radius_/3;
00365       translate( Vec3d(0.0, 0.0, d) );
00366       updateGL();
00367       break;
00368     }
00369 
00370     case ORTHOGRAPHIC_PROJECTION:
00371     {
00372       double d = (double)_event->delta() / 120.0 * 0.2 * factor * orthoWidth_;
00373       orthoWidth_ += d;
00374       updateProjectionMatrix();
00375       updateGL();
00376       break;
00377     }
00378   }
00379 
00380 
00381   // sync views
00382   emit(signalSetView(glstate_->modelview(), glstate_->inverse_modelview()));
00383 }
00384 
00385 
00386 //-----------------------------------------------------------------------------
00387 
00388 
00389 bool QtExaminerViewer::mapToSphere(const QPoint& _v2D, Vec3d& _v3D) const
00390 {
00391   if ( (_v2D.x() >= 0) && (_v2D.x() < (int)glWidth()) &&
00392        (_v2D.y() >= 0) && (_v2D.y() < (int)glHeight()) )
00393   {
00394     double x   = (double)(_v2D.x() - ((double)glWidth() / 2.0))  / (double)glWidth();
00395     double y   = (double)(((double)glHeight() / 2.0) - _v2D.y()) / (double)glHeight();
00396     double sinx         = sin(M_PI * x * 0.5);
00397     double siny         = sin(M_PI * y * 0.5);
00398     double sinx2siny2   = sinx * sinx + siny * siny;
00399 
00400     _v3D[0] = sinx;
00401     _v3D[1] = siny;
00402     _v3D[2] = sinx2siny2 < 1.0 ? sqrt(1.0 - sinx2siny2) : 0.0;
00403 
00404     return true;
00405   }
00406   else return false;
00407 }
00408 
00409 
00410 //-----------------------------------------------------------------------------
00411 
00412 
00413 void QtExaminerViewer::slotAnimation()
00414 {
00415   static int msecs=0, count=0;
00416   QTime t;
00417   t.start();
00418   makeCurrent();
00419   rotate( lastRotationAxis_, lastRotationAngle_ );
00420   updateGL();
00421 
00422   if (!isUpdateLocked()) {
00423     msecs += t.elapsed();
00424     if (count==10) {
00425       assert(statusbar_!=0);
00426       char s[100];
00427       sprintf( s, "%.3f fps", (10000.0 / (float)msecs) );
00428       statusbar_->showMessage(s,2000);
00429       count = msecs = 0;
00430     }
00431     else
00432       ++count;
00433   }
00434 }
00435 
00436 
00437 //=============================================================================
00438 } // namespace QtWidgets
00439 } // namespace ACG
00440 //=============================================================================

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