GLTrackball.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 GLTrackball - IMPLEMENTATION
00048 //
00049 //=============================================================================
00050 
00051 //== INCLUDES =================================================================
00052 
00053 
00054 #include "GLTrackball.hh"
00055 
00056 
00057 //== NAMESPACES ===============================================================
00058 
00059 
00060 namespace ACG {
00061 
00062 
00063 //== IMPLEMENTATION ========================================================== 
00064 
00065 
00066 GLTrackball::
00067 GLTrackball(GLState& _state) 
00068   : glstate_(_state), 
00069     center_(0,0,0) 
00070 {
00071   for (int i=0; i<10; ++i)
00072     button_down_[i] = false;
00073 }
00074 
00075 
00076 //-----------------------------------------------------------------------------
00077 
00078 
00079 void 
00080 GLTrackball::mouse_press(int button, int x, int y)
00081 {
00082   last_point_2D_ = ACG::Vec2i(x, y);
00083   last_point_ok_ = map_to_sphere(last_point_2D_, last_point_3D_);
00084 
00085   button_down_[button] = true;
00086 }
00087 
00088 
00089 //-----------------------------------------------------------------------------
00090 
00091 
00092 void 
00093 GLTrackball::mouse_release(int button, int /* x */ , int /* y */ )
00094 {
00095   last_point_ok_ = false;
00096   button_down_[button] = false;
00097 
00098   // GLUT: button 3 or 4 -> mouse wheel clicked
00099   if (button == 3)       
00100     zoom(0, (int)(last_point_2D_[1] - 0.05*glstate_.viewport_width()));
00101   else if (button == 4)
00102     zoom(0, (int)(last_point_2D_[1] + 0.05*glstate_.viewport_width()));
00103 }
00104 
00105 
00106 //-----------------------------------------------------------------------------
00107 
00108 
00109 void 
00110 GLTrackball::mouse_move(int x, int y)
00111 {
00112   if (button_down_[0] && button_down_[1])
00113     action_ = ZOOM;
00114   else if (button_down_[0])
00115     action_ = ROTATION;
00116   else if (button_down_[1])
00117     action_ = TRANSLATION;
00118 
00119   switch (action_)
00120   {
00121     case ROTATION:    rotation(x, y);     break;
00122     case TRANSLATION: translation(x, y);  break;
00123     case ZOOM:        zoom(x, y);         break;
00124   }
00125 
00126   last_point_2D_ = ACG::Vec2i(x, y);
00127   last_point_ok_ = map_to_sphere(last_point_2D_, last_point_3D_);
00128 }
00129 
00130 
00131 //-----------------------------------------------------------------------------
00132 
00133 
00134 void 
00135 GLTrackball::rotation(int x, int y)
00136 {
00137   if (last_point_ok_) 
00138   {
00139     Vec2i  new_point_2D_;
00140     Vec3f  new_point_3D_;
00141     bool   new_point_ok_;
00142 
00143     new_point_2D_ = ACG::Vec2i(x, y);
00144     new_point_ok_ = map_to_sphere(new_point_2D_, new_point_3D_);
00145     
00146     if (new_point_ok_)
00147     {
00148       Vec3f axis      = (last_point_3D_ % new_point_3D_);
00149       float cos_angle = (last_point_3D_ | new_point_3D_);
00150 
00151       if (fabs(cos_angle) < 1.0) 
00152       {
00153         float angle = 2.0*acos(cos_angle) * 180.0 / M_PI;
00154 
00155         Vec3f t = glstate_.modelview().transform_point(center_);
00156         glstate_.translate(-t[0], -t[1], -t[2], MULT_FROM_LEFT);
00157         glstate_.rotate(angle, axis[0], axis[1], axis[2], MULT_FROM_LEFT);
00158         glstate_.translate( t[0],  t[1],  t[2], MULT_FROM_LEFT);
00159       }
00160     }
00161   }
00162 }
00163 
00164 
00165 //-----------------------------------------------------------------------------
00166 
00167 
00168 void 
00169 GLTrackball::translation(int x, int y)
00170 {
00171   float dx = x - last_point_2D_[0];
00172   float dy = y - last_point_2D_[1];
00173 
00174   float z      = glstate_.modelview().transform_point(center_)[2];
00175   float w      = glstate_.viewport_width();
00176   float h      = glstate_.viewport_height();
00177   float fovy   = glstate_.fovy();
00178   float nearpl = glstate_.near_plane();
00179 
00180   float aspect = w / h;
00181   float top    = tan(fovy/2.0f*M_PI/180.f) * nearpl;
00182   float right  = aspect*top;
00183 
00184   glstate_.translate(-2.0*dx/w*right/nearpl*z, 
00185                      2.0*dy/h*top/nearpl*z, 
00186                      0.0,
00187                      MULT_FROM_LEFT);
00188 }
00189 
00190 
00191 //-----------------------------------------------------------------------------
00192 
00193 
00194 void 
00195 GLTrackball::zoom(int /* x */ , int y)
00196 {
00197   float dy = y - last_point_2D_[1];
00198   float z  = glstate_.modelview().transform_point(center_)[2];
00199   float h  = glstate_.viewport_height();
00200 
00201   glstate_.translate(0.0,
00202                      0.0,
00203                      -2.0*dy/h*z, 
00204                      MULT_FROM_LEFT);
00205 }
00206 
00207 
00208 //-----------------------------------------------------------------------------
00209 
00210 
00211 bool
00212 GLTrackball::map_to_sphere(const Vec2i& _point, Vec3f& _result)
00213 {
00214   float width  = glstate_.viewport_width();
00215   float height = glstate_.viewport_height();
00216   
00217   if ( (_point[0] >= 0) && (_point[0] <= width) &&
00218        (_point[1] >= 0) && (_point[1] <= height) ) 
00219   {
00220     double x            = (_point[0] - 0.5*width)  / width;
00221     double y            = (0.5*height - _point[1]) / height;
00222     double sinx         = sin(M_PI * x * 0.5);
00223     double siny         = sin(M_PI * y * 0.5);
00224     double sinx2siny2   = sinx * sinx + siny * siny;
00225     
00226     _result[0] = sinx;
00227     _result[1] = siny;
00228     _result[2] = sinx2siny2 < 1.0 ? sqrt(1.0 - sinx2siny2) : 0.0;
00229     
00230     return true;
00231   }
00232   else return false;
00233 }
00234 
00235 
00236 //=============================================================================
00237 } // namespace ACG
00238 //=============================================================================

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