00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 #include "domUtils.h"
00024 #include "manipulatedCameraFrame.h"
00025 #include "qglviewer.h"
00026 
00027 #if QT_VERSION >= 0x040000
00028 # include <QMouseEvent>
00029 #endif
00030 
00031 using namespace qglviewer;
00032 using namespace std;
00033 
00039 ManipulatedCameraFrame::ManipulatedCameraFrame()
00040   : driveSpeed_(0.0), flyUpVector_(0.0, 1.0, 0.0)
00041 {
00042   setFlySpeed(0.0);
00043   removeFromMouseGrabberPool();
00044 
00045   connect(&flyTimer_, SIGNAL(timeout()), SLOT(flyUpdate()));
00046 }
00047 
00049 ManipulatedCameraFrame& ManipulatedCameraFrame::operator=(const ManipulatedCameraFrame& mcf)
00050 {
00051   ManipulatedFrame::operator=(mcf);
00052 
00053   setFlySpeed(mcf.flySpeed());
00054   setFlyUpVector(mcf.flyUpVector());
00055 
00056   return *this;
00057 }
00058 
00060 ManipulatedCameraFrame::ManipulatedCameraFrame(const ManipulatedCameraFrame& mcf)
00061   : ManipulatedFrame(mcf)
00062 {
00063   removeFromMouseGrabberPool();
00064   connect(&flyTimer_, SIGNAL(timeout()), SLOT(flyUpdate()));
00065   (*this)=(mcf);
00066 }
00067 
00069 
00073 void ManipulatedCameraFrame::spin()
00074 {
00075   rotateAroundPoint(spinningQuaternion(), revolveAroundPoint());
00076 }
00077 
00078 #ifndef DOXYGEN
00079 
00081 void ManipulatedCameraFrame::flyUpdate()
00082 {
00083   static Vec flyDisp(0.0, 0.0, 0.0);
00084   switch (action_)
00085     {
00086     case QGLViewer::MOVE_FORWARD:
00087       flyDisp.z = -flySpeed();
00088       translate(localInverseTransformOf(flyDisp));
00089       break;
00090     case QGLViewer::MOVE_BACKWARD:
00091       flyDisp.z = flySpeed();
00092       translate(localInverseTransformOf(flyDisp));
00093       break;
00094     case QGLViewer::DRIVE:
00095       flyDisp.z = flySpeed() * driveSpeed_;
00096       translate(localInverseTransformOf(flyDisp));
00097       break;
00098     default:
00099       break;
00100     }
00101 
00102   
00103   
00104   Q_EMIT manipulated();
00105 }
00106 #endif
00107 
00110 void ManipulatedCameraFrame::updateFlyUpVector()
00111 {
00112   flyUpVector_ = inverseTransformOf(Vec(0.0, 1.0, 0.0));
00113 }
00114 
00116 
00118 
00132 QDomElement ManipulatedCameraFrame::domElement(const QString& name, QDomDocument& document) const
00133 {
00134   QDomElement e = ManipulatedFrame::domElement(name, document);
00135   QDomElement mcp = document.createElement("ManipulatedCameraParameters");
00136   mcp.setAttribute("flySpeed", QString::number(flySpeed()));
00137   mcp.appendChild(flyUpVector().domElement("flyUpVector", document));
00138   e.appendChild(mcp);
00139   return e;
00140 }
00141 
00146 void ManipulatedCameraFrame::initFromDOMElement(const QDomElement& element)
00147 {
00148   
00149   
00150   
00151   ManipulatedFrame::initFromDOMElement(element);
00152 
00153   QDomElement child=element.firstChild().toElement();
00154   while (!child.isNull())
00155     {
00156       if (child.tagName() == "ManipulatedCameraParameters")
00157         {
00158           setFlySpeed(DomUtils::floatFromDom(child, "flySpeed", flySpeed()));
00159 
00160           QDomElement schild=child.firstChild().toElement();
00161           while (!schild.isNull())
00162             {
00163               if (schild.tagName() == "flyUpVector")
00164                 setFlyUpVector(Vec(schild));
00165 
00166               schild = schild.nextSibling().toElement();
00167             }
00168         }
00169       child = child.nextSibling().toElement();
00170     }
00171 }
00172 
00173 
00175 
00177 
00178 #ifndef DOXYGEN
00179 
00180 void ManipulatedCameraFrame::startAction(int ma, bool withConstraint)
00181 {
00182   ManipulatedFrame::startAction(ma, withConstraint);
00183 
00184   switch (action_)
00185     {
00186     case QGLViewer::MOVE_FORWARD:
00187     case QGLViewer::MOVE_BACKWARD:
00188     case QGLViewer::DRIVE:
00189 #if QT_VERSION >= 0x040000
00190       flyTimer_.setSingleShot(false);
00191 #endif
00192       flyTimer_.start(10);
00193       break;
00194     default:
00195       break;
00196     }
00197 }
00198 #endif
00199 
00204 void ManipulatedCameraFrame::mouseMoveEvent(QMouseEvent* const event, Camera* const camera)
00205 {
00206   
00207   switch (action_)
00208     {
00209     case QGLViewer::TRANSLATE:
00210       {
00211         const QPoint delta = prevPos_ - event->pos();
00212         Vec trans(static_cast<float>(delta.x()), static_cast<float>(-delta.y()), 0.0);
00213         
00214         switch (camera->type())
00215           {
00216           case Camera::PERSPECTIVE :
00217             trans *= 2.0 * tan(camera->fieldOfView()/2.0) *
00218               fabs((camera->frame()->coordinatesOf(revolveAroundPoint())).z) / camera->screenHeight();
00219             break;
00220           case Camera::ORTHOGRAPHIC :
00221             {
00222               GLdouble w,h;
00223               camera->getOrthoWidthHeight(w, h);
00224               trans[0] *= 2.0 * w / camera->screenWidth();
00225               trans[1] *= 2.0 * h / camera->screenHeight();
00226               break;
00227             }
00228           }
00229         translate(inverseTransformOf(translationSensitivity()*trans));
00230         break;
00231       }
00232 
00233     case QGLViewer::MOVE_FORWARD:
00234       {
00235         Quaternion rot = pitchYawQuaternion(event->x(), event->y(), camera);
00236         rotate(rot);
00237         
00238         
00239         
00240         break;
00241       }
00242 
00243     case QGLViewer::MOVE_BACKWARD:
00244       {
00245         Quaternion rot = pitchYawQuaternion(event->x(), event->y(), camera);
00246         rotate(rot);
00247         
00248         
00249         break;
00250       }
00251 
00252     case QGLViewer::DRIVE:
00253       {
00254         Quaternion rot = turnQuaternion(event->x(), camera);
00255         rotate(rot);
00256         
00257         driveSpeed_ = 0.01 * (event->y() - pressPos_.y());
00258         break;
00259       }
00260 
00261     case QGLViewer::ZOOM:
00262       {
00263         
00264         const float coef = qMax(fabsf((camera->frame()->coordinatesOf(camera->revolveAroundPoint())).z), 0.2f*camera->sceneRadius());
00265         Vec trans(0.0, 0.0, -coef * (event->y() - prevPos_.y()) / camera->screenHeight());
00266         translate(inverseTransformOf(trans));
00267         break;
00268       }
00269 
00270     case QGLViewer::LOOK_AROUND:
00271       {
00272         Quaternion rot = pitchYawQuaternion(event->x(), event->y(), camera);
00273         rotate(rot);
00274         break;
00275       }
00276 
00277     case QGLViewer::ROTATE:
00278       {
00279         Vec trans = camera->projectedCoordinatesOf(revolveAroundPoint());
00280         Quaternion rot = deformedBallQuaternion(event->x(), event->y(), trans[0], trans[1], camera);
00281         
00282         computeMouseSpeed(event);
00283         setSpinningQuaternion(rot);
00284         spin();
00285         break;
00286       }
00287 
00288     case QGLViewer::SCREEN_ROTATE:
00289       {
00290         Vec trans = camera->projectedCoordinatesOf(revolveAroundPoint());
00291 
00292         const float angle = atan2(event->y() - trans[1], event->x() - trans[0]) - atan2(prevPos_.y()-trans[1], prevPos_.x()-trans[0]);
00293 
00294         Quaternion rot(Vec(0.0, 0.0, 1.0), angle);
00295         
00296         computeMouseSpeed(event);
00297         setSpinningQuaternion(rot);
00298         spin();
00299         updateFlyUpVector();
00300         break;
00301       }
00302 
00303     case QGLViewer::ROLL:
00304       {
00305         const float angle = M_PI * (event->x() - prevPos_.x()) / camera->screenWidth();
00306         Quaternion rot(Vec(0.0, 0.0, 1.0), angle);
00307         rotate(rot);
00308         setSpinningQuaternion(rot);
00309         updateFlyUpVector();
00310         break;
00311       }
00312 
00313     case QGLViewer::SCREEN_TRANSLATE:
00314       {
00315         Vec trans;
00316         int dir = mouseOriginalDirection(event);
00317         if (dir == 1)
00318           trans.setValue(static_cast<float>(prevPos_.x() - event->x()), 0.0, 0.0);
00319         else if (dir == -1)
00320           trans.setValue(0.0, static_cast<float>(event->y() - prevPos_.y()), 0.0);
00321 
00322         switch (camera->type())
00323           {
00324           case Camera::PERSPECTIVE :
00325             trans *= 2.0 * tan(camera->fieldOfView()/2.0) *
00326               fabs((camera->frame()->coordinatesOf(revolveAroundPoint())).z) / camera->screenHeight();
00327             break;
00328           case Camera::ORTHOGRAPHIC :
00329             {
00330               GLdouble w,h;
00331               camera->getOrthoWidthHeight(w, h);
00332               trans[0] *= 2.0 * w / camera->screenWidth();
00333               trans[1] *= 2.0 * h / camera->screenHeight();
00334               break;
00335             }
00336           }
00337 
00338         translate(inverseTransformOf(translationSensitivity()*trans));
00339         break;
00340       }
00341 
00342     case QGLViewer::ZOOM_ON_REGION:
00343     case QGLViewer::NO_MOUSE_ACTION:
00344       break;
00345     }
00346 
00347   if (action_ != QGLViewer::NO_MOUSE_ACTION)
00348     {
00349       prevPos_ = event->pos();
00350       if (action_ != QGLViewer::ZOOM_ON_REGION)
00351         
00352         
00353         Q_EMIT manipulated();
00354     }
00355 }
00356 
00357 
00360 void ManipulatedCameraFrame::mouseReleaseEvent(QMouseEvent* const event, Camera* const camera)
00361 {
00362   if ((action_ == QGLViewer::MOVE_FORWARD) || (action_ == QGLViewer::MOVE_BACKWARD) || (action_ == QGLViewer::DRIVE))
00363     flyTimer_.stop();
00364 
00365   if (action_ == QGLViewer::ZOOM_ON_REGION)
00366     camera->fitScreenRegion(QRect(pressPos_, event->pos()));
00367 
00368   ManipulatedFrame::mouseReleaseEvent(event, camera);
00369 }
00370 
00377 void ManipulatedCameraFrame::wheelEvent(QWheelEvent* const event, Camera* const camera)
00378 {
00379   
00380   switch (action_)
00381     {
00382     case QGLViewer::ZOOM:
00383       {
00384         const float wheelSensitivityCoef = 8E-4f;
00385         
00386         const float coef = qMax(fabsf((camera->frame()->coordinatesOf(camera->revolveAroundPoint())).z), 0.2f*camera->sceneRadius());
00387         Vec trans(0.0, 0.0, coef * event->delta() * wheelSensitivity() * wheelSensitivityCoef);
00388         translate(inverseTransformOf(trans));
00389         Q_EMIT manipulated();
00390         break;
00391       }
00392     case QGLViewer::MOVE_FORWARD:
00393     case QGLViewer::MOVE_BACKWARD:
00394       
00395       translate(inverseTransformOf(Vec(0.0, 0.0, 0.2*flySpeed()*event->delta())));
00396       Q_EMIT manipulated();
00397       break;
00398     default:
00399       break;
00400     }
00401 
00402   
00403   if (previousConstraint_)
00404     setConstraint(previousConstraint_);
00405 
00406   
00407   
00408   
00409   
00410   const int finalDrawAfterWheelEventDelay = 400;
00411 
00412   
00413 #if QT_VERSION >= 0x040000
00414   flyTimer_.setSingleShot(true);
00415   flyTimer_.start(finalDrawAfterWheelEventDelay);
00416 #else
00417   flyTimer_.start(finalDrawAfterWheelEventDelay, true);
00418 #endif
00419 
00420   
00421   
00422   
00423   action_ = QGLViewer::NO_MOUSE_ACTION;
00424 }
00425 
00427 
00429 Quaternion ManipulatedCameraFrame::turnQuaternion(int x, const Camera* const camera)
00430 {
00431   return Quaternion(Vec(0.0, 1.0, 0.0), rotationSensitivity()*(prevPos_.x()-x)/camera->screenWidth());
00432 }
00433 
00436 Quaternion ManipulatedCameraFrame::pitchYawQuaternion(int x, int y, const Camera* const camera)
00437 {
00438   const Quaternion rotX(Vec(1.0, 0.0, 0.0), rotationSensitivity()*(prevPos_.y()-y)/camera->screenHeight());
00439   const Quaternion rotY(transformOf(flyUpVector()), rotationSensitivity()*(prevPos_.x()-x)/camera->screenWidth());
00440   return rotY * rotX;
00441 }