Home | History | Annotate | Download | only in opengl
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud (at) inria.fr>
      5 //
      6 // This Source Code Form is subject to the terms of the Mozilla
      7 // Public License v. 2.0. If a copy of the MPL was not distributed
      8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9 
     10 #include "trackball.h"
     11 #include "camera.h"
     12 
     13 using namespace Eigen;
     14 
     15 void Trackball::track(const Vector2i& point2D)
     16 {
     17   if (mpCamera==0)
     18     return;
     19   Vector3f newPoint3D;
     20   bool newPointOk = mapToSphere(point2D, newPoint3D);
     21 
     22   if (mLastPointOk && newPointOk)
     23   {
     24     Vector3f axis = mLastPoint3D.cross(newPoint3D).normalized();
     25     float cos_angle = mLastPoint3D.dot(newPoint3D);
     26     if ( internal::abs(cos_angle) < 1.0 )
     27     {
     28       float angle = 2. * acos(cos_angle);
     29       if (mMode==Around)
     30         mpCamera->rotateAroundTarget(Quaternionf(AngleAxisf(angle, axis)));
     31       else
     32         mpCamera->localRotate(Quaternionf(AngleAxisf(-angle, axis)));
     33     }
     34   }
     35 
     36   mLastPoint3D = newPoint3D;
     37   mLastPointOk = newPointOk;
     38 }
     39 
     40 bool Trackball::mapToSphere(const Vector2i& p2, Vector3f& v3)
     41 {
     42   if ((p2.x() >= 0) && (p2.x() <= int(mpCamera->vpWidth())) &&
     43       (p2.y() >= 0) && (p2.y() <= int(mpCamera->vpHeight())) )
     44   {
     45     double x  = (double)(p2.x() - 0.5*mpCamera->vpWidth())  / (double)mpCamera->vpWidth();
     46     double y  = (double)(0.5*mpCamera->vpHeight() - p2.y()) / (double)mpCamera->vpHeight();
     47     double sinx         = sin(M_PI * x * 0.5);
     48     double siny         = sin(M_PI * y * 0.5);
     49     double sinx2siny2   = sinx * sinx + siny * siny;
     50 
     51     v3.x() = sinx;
     52     v3.y() = siny;
     53     v3.z() = sinx2siny2 < 1.0 ? sqrt(1.0 - sinx2siny2) : 0.0;
     54 
     55     return true;
     56   }
     57   else
     58     return false;
     59 }
     60