trackball.cpp
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 
00024 #include <GL/glew.h>
00025 #include "trackball.h"
00026 #include<set>
00027 
00028 #include <wrap/gl/math.h>
00029 #include <wrap/gl/space.h>
00030 
00031 using namespace vcg;
00032 
00033 Transform::Transform() {
00034   track.SetIdentity();
00035   radius=1.0f;
00036   center=Point3f(0,0,0);
00037 }
00038 
00039 Trackball::Trackball(): current_button(0), current_mode(NULL), inactive_mode(NULL),
00040                         dragging(false), last_time(0), spinnable(true), spinning(false),
00041                         history_size(10), fixedTimestepMode(false) {
00042   setDefaultMapping ();
00043 }
00044 
00045 Trackball::~Trackball()
00046 {
00047         ClearModes();
00048         delete  inactive_mode;
00049 }
00050 
00051 void Trackball::ClearModes()
00052 {
00053         // Note: people ofter maps different keys to the same modes.
00054         // so we should avoid double deletion of these double referenced modes.
00055         std::set<TrackMode *> goodModes;
00056         std::map<int, TrackMode *>::iterator it;
00057   for(it = modes.begin(); it != modes.end(); it++)
00058                 if ((*it).second) goodModes.insert( (*it).second);
00059 
00060         std::set<TrackMode *>::iterator its;
00061         for(its = goodModes.begin(); its != goodModes.end(); its++)
00062                         delete *its;
00063 
00064         modes.clear();
00065 }
00066 
00067 void Trackball::setDefaultMapping () {
00068   idle_and_keys_mode = NULL;
00069 
00070   inactive_mode = new InactiveMode ();
00071         ClearModes();
00072   modes[0] = NULL;
00073 
00074   modes[BUTTON_MIDDLE | KEY_ALT] =
00075   modes[BUTTON_LEFT] = new SphereMode ();
00076 
00077   modes[BUTTON_LEFT | KEY_CTRL] = new PanMode ();
00078 
00079   modes[BUTTON_MIDDLE] = new PanMode ();
00080 
00081   modes[WHEEL] =
00082   modes[BUTTON_LEFT | KEY_SHIFT] = new ScaleMode ();
00083 
00084   modes[BUTTON_LEFT | KEY_ALT] = new ZMode ();
00085 
00086 }
00087 
00088 void Trackball::SetIdentity() {
00089   track.SetIdentity();
00090   Reset();
00091 }
00092 void Trackball::SetPosition(const Point3f &c, int /* millisec */) {
00093   center = c;
00094 }
00095 
00096 void Trackball::GetView() {
00097   camera.GetView();
00098 }
00099 
00100 // the drawing code has been moved to the trackmodes
00101 void Trackball::DrawPostApply() {
00102         if(current_mode !=NULL){
00103                 current_mode->Draw(this);
00104         }else{
00105                 if (inactive_mode != NULL) inactive_mode->Draw(this);
00106   }
00107 }
00108 
00109 void Trackball::Apply () {
00110   glTranslate (center);
00111   glMultMatrix (track.Matrix());
00112   glTranslate (-center);
00113 }
00114 
00115 void Trackball::ApplyInverse() {
00116   glTranslate(center);
00117   glMultMatrix(track.InverseMatrix());
00118   glTranslate(-center);
00119 }
00120 
00121 // T(c) S R T(t) T(-c) => S R T(S^(-1) R^(-1)(c) + t - c)
00122 Matrix44f Trackball::Matrix() const{
00123   #ifndef VCG_USE_EIGEN
00124   Matrix44f r; track.rot.ToMatrix(r);
00125   Matrix44f sr    = Matrix44f().SetScale(track.sca, track.sca, track.sca) * r;
00126   Matrix44f s_inv = Matrix44f().SetScale(1/track.sca, 1/track.sca, 1/track.sca);
00127   Matrix44f t     = Matrix44f().SetTranslate(s_inv*r.transpose()*center + track.tra - center);
00128 
00129   return Matrix44f(sr*t);
00130   #else
00131   Eigen::Quaternionf rot(track.rot);
00132   Eigen::Translation3f tr( (1/track.sca) * (rot.inverse() * center) + track.tra - center );
00133   return ( Eigen::Scaling3f(track.sca) * (rot * tr) ).matrix();
00134   #endif
00135 }
00136 
00137 Matrix44f Trackball::InverseMatrix() const{
00138   return Inverse(Matrix());
00139 }
00140 
00141 void Trackball::Scale(const float s)
00142 {
00143   track.sca*=s;
00144 }
00145 
00146 void Trackball::Translate(Point3f tr)
00147 {
00148   Quaternionf irot = track.rot;
00149   irot.Invert();
00150   track.tra = last_track.tra + irot.Rotate(tr)/track.sca;
00151 }
00152 
00153 /***************************************************************/
00154 // DrawCircle () e DrawPlane() have been moved to trackutils.h
00155 // the drawing code has been moved to the trackmodes
00156 /*
00157 void Trackball::DrawCircle() {
00158   int nside=DH.CircleStep;
00159   const double pi2=3.14159265*2.0;
00160   glBegin(GL_LINE_LOOP);
00161   for(double i=0;i<nside;i++){
00162     glNormal3d(cos(i*pi2/nside), sin(i*pi2/nside),  0.0);
00163     glVertex3d(cos(i*pi2/nside), sin(i*pi2/nside),  0.0);
00164   }
00165   glEnd();
00166   DrawPlaneHandle();
00167 }
00168 
00169 void Trackball::DrawPlane() {
00170   const int nl=10;
00171   float w=5.0f/3.0f;
00172   float u;
00173   glBegin(GL_LINES);
00174   glNormal3f(0.0,0.0,1.0);
00175   for( u=-w; u<=w+0.01f; u+=2*w/nl){
00176     glVertex3f(-w,      +u,     0);
00177     glVertex3f(+w,      +u,     0);
00178     glVertex3f(+u,      -w, 0);
00179     glVertex3f(+u,      +w, 0);
00180   }
00181   glEnd();
00182 }
00183 */
00184 
00185 void Trackball::ToAscii(char* result){
00186   float * f = (float*) &track;
00187   sprintf(result, "trackball(%f,%f,%f,%f,%f,%f,%f,%f)",
00188                   f[0],f[1],f[2],f[3],f[4],f[5],f[6],f[7] );
00189 }
00190 
00191 bool Trackball::SetFromAscii(const char * st){
00192   float * f = (float*) &track;
00193   int res=  sscanf(st, "trackball(%f,%f,%f,%f,%f,%f,%f,%f)",
00194                   f+0,f+1,f+2,f+3,f+4,f+5,f+6,f+7 );
00195 
00196   return (res==8);
00197 }
00198 
00199 // DrawPlaneHandle() e DrawIcon() have been moved to trackutils.h
00200 // the drawing code has been moved to the trackmodes
00201 /*
00202 void Trackball::DrawPlaneHandle() {
00203   float r=1.0;
00204   float dr=r/10.0f;
00205   glBegin(GL_LINE_STRIP);
00206   glVertex3f(+r+dr,   +r,   0.0);
00207   glVertex3f(+r   ,   +r+dr,0.0);
00208   glVertex3f(+r-dr,   +r,   0.0);
00209   glVertex3f(+r   ,   +r-dr,0.0);
00210   glVertex3f(+r+dr,   +r,   0.0);
00211   glEnd();
00212   glBegin(GL_LINE_STRIP);
00213   glVertex3f(-r+dr,   -r,   0.0);
00214   glVertex3f(-r   ,   -r+dr,0.0);
00215   glVertex3f(-r-dr,   -r,   0.0);
00216   glVertex3f(-r   ,   -r-dr,0.0);
00217   glVertex3f(-r+dr,   -r,   0.0);
00218   glEnd();
00219 }
00220 
00221 void Trackball::DrawIcon() {
00222   glPushMatrix();
00223 
00224   glScale(radius);
00226   float amb[4] ={.3f,.3f,.3f,1.0f};
00227   float col[4] ={.5f,.5f,.8f,1.0f};
00228   //float col2[4]={.9f,.9f,1.0f,1.0f};
00229   glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT);
00230 
00231 
00232   if(current_mode == NULL ) glLineWidth(DH.LineWidthStill);
00233                        else glLineWidth(DH.LineWidthMoving);
00234 
00235   glEnable(GL_LIGHTING);
00236   glEnable(GL_LIGHT0);
00237   glEnable(GL_LINE_SMOOTH);
00238   glEnable(GL_BLEND);
00239   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00240   glColor(DH.color);
00241 
00242   glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,amb);
00243   glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,col);
00244   glPushMatrix();
00245     DrawCircle();
00246     glPushMatrix();
00247 
00248       glRotatef(90,1,0,0);
00249       DrawCircle();
00250       glRotatef(90,0,1,0);
00251       DrawCircle();
00252 
00253     glPopMatrix();
00254   glPopMatrix();
00255 
00256   //glColor4f(1.0,.8f,.8f,1.0f);
00257 
00258   glPopAttrib();
00259 
00260   glPopMatrix();
00261 }
00262 */
00263 
00264 void Trackball::Reset() {
00265   track.SetIdentity();
00266   undo_track = track;
00267   std::map<int, TrackMode *>::iterator i;
00268   for(i = modes.begin(); i != modes.end(); i++){
00269    TrackMode * mode=(*i).second;
00270    if(mode!=NULL)
00271      mode->Reset();
00272   }
00273   if (inactive_mode != NULL) inactive_mode->Reset();
00274  }
00275 
00276 //interface
00277 void Trackball::MouseDown(int button) {
00278   undo_track = track;
00279   current_button |= button;
00280   SetCurrentAction();
00281   Hits.clear();
00282 }
00283 void Trackball::MouseDown(int x, int y, int button) {
00284   undo_track = track;
00285   current_button |= button;
00286   SetCurrentAction();
00287   last_point = Point3f((float)x, (float)y, 0);
00288   Hits.clear();
00289 }
00290 
00291 void Trackball::MouseMove(int x, int y) {
00292   if(current_mode == NULL) return;
00293   if(last_point[2] == -1) { //changed mode in the middle of moving
00294     last_point = Point3f((float)x, (float)y, 0);
00295     return;
00296   }
00297   undo_track = track;
00298   current_mode->Apply(this, Point3f(float(x), float(y), 0));
00299 }
00300 
00301 bool Trackball::IsAnimating(unsigned int msec){
00302         bool res;
00303         if(idle_and_keys_mode == NULL) res=false; else res=idle_and_keys_mode->IsAnimating(this);
00304 
00305         if (!fixedTimestepMode) {
00306         if (msec==0) msec = clock()*1000/CLOCKS_PER_SEC;
00307           if (!res) {
00308           last_time = msec;
00309           }
00310         }
00311         return res;
00312 }
00313 
00314 void Trackball::Sync(unsigned int msec) {
00315         if (!fixedTimestepMode) Animate(msec);
00316 }
00317 
00318 void Trackball::Animate(unsigned int msec){
00319         unsigned int delta;
00320         if (fixedTimestepMode) delta=msec;
00321         else {
00322                 if (msec==0) msec = clock()*1000/CLOCKS_PER_SEC;
00323     delta = msec -last_time;
00324           last_time = msec;
00325         }
00326         if(idle_and_keys_mode == NULL) return;
00327         idle_and_keys_mode->Animate(delta,this);
00328 }
00329 
00330 void Trackball::MouseUp(int /* x */, int /* y */, int button) {
00331   undo_track = track;
00332         ButtonUp(vcg::Trackball::Button(button));
00333   //current_button &= (~button);
00334   //SetCurrentAction();
00335 }
00336 
00337 // it assumes that a notch of 1.0 is a single step of the wheel
00338 void Trackball::MouseWheel(float notch)
00339 {
00340   undo_track = track;
00341         int buttons = current_button;
00342         current_button = WHEEL | (buttons&(KEY_SHIFT|KEY_CTRL|KEY_ALT));
00343         SetCurrentAction();
00344   if (current_mode == NULL)
00345   {
00346     //ScaleMode scalemode;
00347     //scalemode.Apply (this, notch);
00348   }
00349         else
00350         {
00351     current_mode->Apply(this, notch);
00352   }
00353         current_button = buttons;
00354         SetCurrentAction();
00355 }
00356 
00357 void Trackball::MouseWheel(float notch, int button)
00358 {
00359   undo_track = track;
00360   current_button |= button;
00361   SetCurrentAction();
00362   if (current_mode == NULL) {
00363     ScaleMode scalemode;
00364     scalemode.Apply (this, notch);
00365   } else {
00366     current_mode->Apply (this, notch);
00367   }
00368   current_button &= (~button);
00369   SetCurrentAction ();
00370 }
00371 
00372 void Trackball::ButtonDown(Trackball::Button button, unsigned int msec) {
00373         Sync(msec);
00374   bool old_sticky=false, new_sticky=false;
00375   assert (modes.count (0));
00376 
00377         Button b=Button(current_button & MODIFIER_MASK);
00378   if ( ( modes.count (b) ) && ( modes[b] != NULL ) ) old_sticky = modes[b]->isSticky();
00379 
00380   current_button |= button;
00381         b=Button(current_button & MODIFIER_MASK);
00382         if ( ( modes.count (b) ) && ( modes[b] != NULL ) ) new_sticky = modes[b]->isSticky();
00383 
00384   if ( !old_sticky && !new_sticky) SetCurrentAction();
00385 
00386 }
00387 
00388 void Trackball::ButtonUp(Trackball::Button button) {
00389   bool old_sticky=false, new_sticky=false;
00390   assert (modes.count (0));
00391 
00392         Button b=Button(current_button & MODIFIER_MASK);
00393   if ( ( modes.count (b) ) && ( modes[b] != NULL ) ) old_sticky = modes[b]->isSticky();
00394 
00395   current_button &= (~button);
00396         b=Button(current_button & MODIFIER_MASK);
00397         if ( ( modes.count (b) ) && ( modes[b] != NULL ) ) new_sticky = modes[b]->isSticky();
00398 
00399   if ( !old_sticky && !new_sticky) SetCurrentAction();
00400 }
00401 
00402 void Trackball::Undo(){
00403   track = undo_track;
00404   if(current_mode != NULL)
00405     current_mode->Undo();
00406 }
00407 
00408 
00409 //spinning interface
00410 void Trackball::SetSpinnable(bool /* on*/ ){}
00411 bool Trackball::IsSpinnable() {
00412   return spinnable;
00413 }
00414 void Trackball::SetSpinning(Quaternionf &/* spin*/){}
00415 void Trackball::StopSpinning(){}
00416 bool Trackball::IsSpinning() {
00417   return spinning;
00418 }
00419 
00420 //navigation interface:
00421 void Trackball::Back(){}
00422 void Trackball::Forward(){}
00423 void Trackball::Home(){}
00424 void Trackball::HistorySize(int /* length */){}
00425 
00426 void Trackball::SetCurrentAction ()
00427 {
00428   //I use strict matching.
00429   assert (modes.count (0));
00430   if (!modes.count (current_button & MODIFIER_MASK)) {
00431     current_mode = NULL;
00432   } else {
00433     current_mode = modes[current_button & MODIFIER_MASK];
00434     if(current_mode != NULL)
00435       current_mode->SetAction();
00436   }
00437   last_point = Point3f (0, 0, -1);
00438   last_track = track;
00439 }
00440 
00442 //Point3f Trackball::ScreenOrigin() {
00443 //  return camera.Project(ModelOrigin());
00444 //}
00445 
00446 
00447 //return center of trackball in Model coordinates
00448 //Point3f Trackball::ModelOrigin() {
00449 //  return center;
00450 //}
00451 
00452 //Matrix44f Trackball::ScreenToModel() {
00453 //  return camera.inverse;
00454 //}
00455 //
00456 //Similarityf Trackball::ModelToLocal() {
00457 //  Similarityf m = local * last_track;
00458 //  return m;
00459 //}
00460 


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:37:26