00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00054
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 ) {
00093 center = c;
00094 }
00095
00096 void Trackball::GetView() {
00097 camera.GetView();
00098 }
00099
00100
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
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
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
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
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
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
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) {
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 , int , int button) {
00331 undo_track = track;
00332 ButtonUp(vcg::Trackball::Button(button));
00333
00334
00335 }
00336
00337
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
00347
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
00410 void Trackball::SetSpinnable(bool ){}
00411 bool Trackball::IsSpinnable() {
00412 return spinnable;
00413 }
00414 void Trackball::SetSpinning(Quaternionf &){}
00415 void Trackball::StopSpinning(){}
00416 bool Trackball::IsSpinning() {
00417 return spinning;
00418 }
00419
00420
00421 void Trackball::Back(){}
00422 void Trackball::Forward(){}
00423 void Trackball::Home(){}
00424 void Trackball::HistorySize(int ){}
00425
00426 void Trackball::SetCurrentAction ()
00427 {
00428
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
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460