TrackballNode.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 //
00048 //  CLASS TrackballNode - IMPLEMENTATION
00049 //
00050 //=============================================================================
00051 
00052 
00053 //== INCLUDES =================================================================
00054 
00055 
00056 #include "TrackballNode.hh"
00057 #include "../Math/GLMatrixT.hh"
00058 #include "../GL/gl.hh"
00059 
00060 #include <QMouseEvent>
00061 #include <QEvent>
00062 
00063 
00064 //== NAMESPACES ===============================================================
00065 
00066 
00067 namespace ACG {
00068 namespace SceneGraph {
00069 
00070 
00071 //== IMPLEMENTATION ========================================================== 
00072 
00073 
00074 void
00075 TrackballNode::draw(GLState& /* _state */ , unsigned int /* _drawMode */ )
00076 {
00077   // draw the trackball
00078   if (drawTrackball_) 
00079   {
00080     glDisable(GL_LIGHTING);
00081     glShadeModel( GL_FLAT );
00082     glPushMatrix();
00083     glTranslatef(center()[0], center()[1], center()[2]);
00084     glutWireSphere(radius_, 20, 20);
00085     glPopMatrix();
00086   }
00087 
00088 
00089   // draw the coord axes
00090   if (drawAxes_)
00091   {
00092     // store original settings
00093     GLfloat backupColor[4], backupLineWidth;
00094     glGetFloatv(GL_CURRENT_COLOR, backupColor);
00095     glGetFloatv(GL_LINE_WIDTH, &backupLineWidth);
00096     
00097     glDisable(GL_LIGHTING);
00098     glShadeModel( GL_FLAT );
00099     glLineWidth(3.0);
00100 
00101     glColor3f(1.0, 0.0, 0.0);
00102     glBegin(GL_LINES);
00103     glVertex(center());
00104     glVertex(center() + radius_*xAxis_);
00105     glEnd();
00106 
00107     glColor3f(0.0, 1.0, 0.0);
00108     glBegin(GL_LINES);
00109     glVertex(center());
00110     glVertex(center() + radius_*yAxis_);
00111     glEnd();
00112 
00113     glColor3f(0.0, 0.0, 1.0);
00114     glBegin(GL_LINES);
00115     glVertex(center());
00116     glVertex(center() + radius_*zAxis_);
00117     glEnd();
00118 
00119     // restore original settings
00120     glColor4fv(backupColor);
00121     glLineWidth(backupLineWidth);
00122   }
00123 }
00124 
00125 
00126 //----------------------------------------------------------------------------
00127 
00128 
00129 void
00130 TrackballNode::mouseEvent(GLState& _state, QMouseEvent* _event)
00131 {
00132   Vec3d         oldPoint3D;
00133   Vec2i         newPoint2D(_event->pos().x(), _event->pos().y());
00134   Vec3d         newPoint3D;
00135 
00136 
00137   switch (_event->type())
00138   {
00139     case QEvent::MouseButtonPress:
00140     {
00141       break;
00142     }
00143 
00144 
00145     case QEvent::MouseButtonDblClick:
00146     {
00147       if (mapToSphere(_state, oldPoint2D_, oldPoint3D))
00148       {
00149         // toggle drawTrackball_
00150         if (_event->button() == Qt::LeftButton)
00151           drawTrackball_ = !drawTrackball_;
00152 
00153         // toggle drawAxes_
00154         if (_event->button() == Qt::MidButton)
00155           drawAxes_ = !drawAxes_;
00156       }
00157       break;
00158     }
00159     
00160     
00161     case QEvent::MouseMove:
00162     {
00163       bool hit0 = mapToSphere(_state, newPoint2D, newPoint3D);
00164       bool hit1 = mapToSphere(_state, oldPoint2D_, oldPoint3D);
00165 
00166       if (hit0 && hit1)
00167       {
00168 
00169         // scaling
00170         if ((_event->button() & Qt::LeftButton) &&
00171             (_event->button() & Qt::MidButton))
00172         {
00173           double s = 1.0 + ((double) (newPoint2D[1] - oldPoint2D_[1]) /
00174                            (double) _state.viewport_height());
00175           scale(s);
00176         }
00177 
00178 
00179         // translation
00180         else if (_event->button() & Qt::MidButton)
00181         {
00182           double value_x = (radius_ * ((newPoint2D[0] - oldPoint2D_[0])) 
00183                            * 2.0 / (double) _state.viewport_width());
00184           
00185           double value_y = (radius_ * ((newPoint2D[1] - oldPoint2D_[1]))
00186                            * 2.0 / (double) _state.viewport_height());
00187           
00188           
00189           /* need inverse transposed matrix in order to
00190              transform direction vectors */
00191           GLMatrixd m = inverse_matrix();
00192           m.transpose();
00193 
00194 
00195           Vec3d dx, dy;
00196 
00197           // axis aligned
00198           if (drawAxes_)
00199           {
00200             dx = m.transform_point(xAxis_);
00201             dy = m.transform_point(yAxis_);
00202           }
00203 
00204           // screen space translation
00205           else 
00206           {
00207             dx = m.transform_vector(_state.right());
00208             dy = m.transform_vector(_state.up());
00209           }
00210           
00211           dx.normalize();
00212           dy.normalize();
00213           translate(value_x*dx - value_y*dy);
00214         }
00215       
00216 
00217 
00218         // rotation
00219         else if (_event->button() & Qt::LeftButton) 
00220         {
00221           Vec3d axis = oldPoint3D % newPoint3D; 
00222           double cos_angle = ( oldPoint3D | newPoint3D );
00223 
00224           
00225           if (fabs(cos_angle) < 1.0)
00226           {
00227             // rotate coord axes
00228             if (_event->modifiers() & Qt::AltModifier)
00229             {
00230               GLMatrixd mat;
00231               
00232               mat.identity();
00233               mat.rotate(acos(cos_angle)*180.0/M_PI, axis);
00234               
00235               /* transform_point works since only 
00236                  rotations and no translations are
00237                  involved */
00238               xAxis_ = mat.transform_point(xAxis_);
00239               yAxis_ = mat.transform_point(yAxis_);
00240               zAxis_ = mat.transform_point(zAxis_);
00241             }
00242             
00243             // normal rotation
00244             else  rotate(acos(cos_angle)*180.0/M_PI, axis);
00245           }
00246         }
00247       }
00248 
00249 
00250       break;
00251     }
00252 
00253     default: // avoid warning
00254       break;
00255   }
00256 
00257 
00258   // store 2D point
00259   oldPoint2D_ = newPoint2D;
00260 }
00261 
00262 
00263 //----------------------------------------------------------------------------
00264 
00265 
00266 bool
00267 TrackballNode::mapToSphere( GLState& _state,
00268                             const Vec2i& _v2, 
00269                             Vec3d& _v3 )
00270 {
00271   // Qt -> GL coordinate systems
00272   unsigned int x = _v2[0];
00273   unsigned int y = _state.context_height() - _v2[1];
00274 
00275 
00276   // get ray from eye through pixel (trackball coords)
00277   Vec3d origin, direction;
00278   _state.viewing_ray(x, y, origin, direction);
00279 
00280 
00281   // translate and scale trackball to unit sphere
00282   origin -= center();
00283   origin /= radius_;
00284 
00285 
00286   // calc sphere-ray intersection
00287   // (sphere is centered at origin, has radius 1)
00288   double a = direction.sqrnorm(),
00289         b = 2.0 * (origin | direction),
00290         c = origin.sqrnorm() - 1.0,
00291         d = b*b - 4.0*a*c,
00292         t;
00293 
00294   if      (d <  0.0)  return false;
00295   else if (d == 0.0)  t = -b / (2.0*a);
00296   else 
00297   { 
00298     // t1 = (-b - sqrt(d)) / (2.0*a),  t2 = (-b + sqrt(d)) / (2.0*a)
00299     a = 1.0 / (2.0*a);
00300     d = sqrt(d);
00301     double t1 = (-b - d) * a;
00302     double t2 = (-b + d) * a;
00303     t = (t1 < t2) ? t1 : t2;
00304   }
00305 
00306   _v3 = origin + direction*t;
00307   
00308   return true;
00309 }
00310 
00311 
00312 //=============================================================================
00313 } // namespace SceneGraph
00314 } // namespace ACG
00315 //=============================================================================

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