/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: not supported by cvs2svn $ Revision 1.21 2007/06/20 12:59:43 corsini adjust wheel back-compatibility Revision 1.20 2007/06/13 17:15:08 benedetti Added one-level undo system and sticky trackmodes. Revision 1.19 2007/05/15 15:00:27 benedetti Moved the drawing code to trackmodes, some other minor changes Revision 1.18 2007/02/26 01:30:02 cignoni Added reflection Name Revision 1.17 2007/01/15 15:04:15 tarini added "ToAscii" and "SetFromAscii" methods to load/store current trackball status from/to ascii strings (intended uses: clipboard operations and comments inside png snapshots!) Revision 1.16 2006/07/26 13:54:45 cignoni Reversed the direction of wheel scaling and added middle mouse panning Revision 1.15 2006/02/13 13:15:52 cignoni Added Scale and Translate methods. Added many drawing hints and raised the default num. of steps when drawing circles. Added MouseDown without coords (for remembering changes of keys modifiers) Added ZMode to the default modes under Alt+left Added DrawPostApply (to be completed) Revision 1.14 2005/10/17 01:29:46 cignoni Main restructuring. Removed the Draw function and slightly changed the meaning of the trackball itself. See the notes at the beginning of trackball.h Revision 1.13 2005/04/17 17:48:24 ganovelli modes deallocation commented (quick and dirty solution..to debug) Revision 1.12 2004/12/17 10:28:10 ricciodimare *** empty log message *** Revision 1.11 2004/09/28 15:30:12 ponchio Added a 'else'. Revision 1.10 2004/09/09 14:38:52 ponchio #include #include #include "trackball.h" #include #include using namespace vcg; Transform::Transform() { track.SetIdentity(); radius=1.0f; center=Point3f(0,0,0); } Trackball::Trackball(): current_button(0), current_mode(NULL), inactive_mode(NULL), dragging(false), spinnable(true), spinning(false), history_size(10){ setDefaultMapping (); } Trackball::~Trackball() { //map::iterator i; //for(i = modes.begin(); i != modes.end(); i++) // delete (*i).second; } void Trackball::setDefaultMapping () { inactive_mode = new InactiveMode (); modes.clear (); modes[0] = NULL; modes[BUTTON_LEFT] = new SphereMode (); modes[BUTTON_LEFT | KEY_CTRL] = new PanMode (); modes[BUTTON_MIDDLE] = new PanMode (); modes[BUTTON_LEFT | KEY_SHIFT] = new ScaleMode (); modes[BUTTON_LEFT | KEY_ALT] = new ZMode (); modes[WHEEL] = new ScaleMode (); SetCurrentAction (); } void Trackball::SetIdentity() { track.SetIdentity(); Reset(); } void Trackball::SetPosition(const Point3f &c, int /* millisec */) { center = c; } void Trackball::GetView() { camera.GetView(); } // the drawing code has been moved to the trackmodes void Trackball::DrawPostApply() { if(current_mode !=NULL){ current_mode->Draw(this); }else{ assert(inactive_mode != NULL); inactive_mode->Draw(this); } } void Trackball::Apply () { glTranslate (center); glMultMatrix (track.Matrix ()); glTranslate (-center); } void Trackball::Apply(bool ToDraw) { Apply(); if(ToDraw){ DrawPostApply(); } } void Trackball::ApplyInverse() { glTranslate(center); glMultMatrix(track.InverseMatrix()); glTranslate(-center); } void Trackball::Scale(const float s) { track.sca*=s; } void Trackball::Translate(Point3f tr) { Matrix44f m; track.rot.ToMatrix(m); track.tra = last_track.tra + Inverse(m)*tr/track.sca; } /***************************************************************/ // DrawCircle () e DrawPlane() have been moved to trackutils.h // the drawing code has been moved to the trackmodes /* void Trackball::DrawCircle() { int nside=DH.CircleStep; const double pi2=3.14159265*2.0; glBegin(GL_LINE_LOOP); for(double i=0;i::iterator i; for(i = modes.begin(); i != modes.end(); i++){ TrackMode * mode=(*i).second; if(mode!=NULL) mode->Reset(); } assert(inactive_mode != NULL); inactive_mode->Reset(); } //interface void Trackball::MouseDown(int button) { undo_track = track; current_button |= button; SetCurrentAction(); Hits.clear(); } void Trackball::MouseDown(int x, int y, int button) { undo_track = track; current_button |= button; SetCurrentAction(); last_point = Point3f((float)x, (float)y, 0); Hits.clear(); } void Trackball::MouseMove(int x, int y) { if(current_mode == NULL) return; if(last_point[2] == -1) { //changed mode in the middle of moving last_point = Point3f((float)x, (float)y, 0); return; } undo_track = track; current_mode->Apply(this, Point3f(float(x), float(y), 0)); } void Trackball::MouseUp(int /* x */, int /* y */, int button) { undo_track = track; current_button &= (~button); SetCurrentAction(); } // it assumes that a notch of 1.0 is a single step of the wheel void Trackball::MouseWheel(float notch) { undo_track = track; int buttons = current_button; current_button = WHEEL | (buttons&(KEY_SHIFT|KEY_CTRL|KEY_ALT)); SetCurrentAction(); if (current_mode == NULL) { ScaleMode scalemode; scalemode.Apply (this, notch); } else { current_mode->Apply(this, notch); } current_button = buttons; SetCurrentAction(); } void Trackball::MouseWheel(float notch, int button) { undo_track = track; current_button |= button; SetCurrentAction(); if (current_mode == NULL) { ScaleMode scalemode; scalemode.Apply (this, notch); } else { current_mode->Apply (this, notch); } current_button &= (~button); SetCurrentAction (); } void Trackball::ButtonDown(Trackball::Button button) { bool old_sticky=false, new_sticky=false; assert (modes.count (0)); if ( ( modes.count (current_button) ) && ( modes[current_button] != NULL ) ) { old_sticky = modes[current_button]->isSticky(); } current_button |= button; if ( ( modes.count (current_button) ) && ( modes[current_button] != NULL ) ) { new_sticky = modes[current_button]->isSticky(); } if ( old_sticky || new_sticky) return; SetCurrentAction(); } void Trackball::ButtonUp(Trackball::Button button) { bool old_sticky=false, new_sticky=false; assert ( modes.count (0) ); if ( ( modes.count (current_button) ) && ( modes[current_button] != NULL ) ) { old_sticky = modes[current_button]->isSticky(); } current_button &= (~button); if ( ( modes.count (current_button) ) && ( modes[current_button] != NULL ) ) { new_sticky = modes[current_button]->isSticky(); } if ( old_sticky || new_sticky) return; SetCurrentAction(); } void Trackball::Undo(){ track = undo_track; if(current_mode != NULL) current_mode->Undo(); } //spinning interface void Trackball::SetSpinnable(bool /* on*/ ){} bool Trackball::IsSpinnable() { return spinnable; } void Trackball::SetSpinning(Quaternionf &/* spin*/){} void Trackball::StopSpinning(){} bool Trackball::IsSpinning() { return spinning; } //navigation interface: void Trackball::Back(){} void Trackball::Forward(){} void Trackball::Home(){} void Trackball::HistorySize(int /* length */){} void Trackball::SetCurrentAction () { //I use strict matching. assert (modes.count (0)); if (!modes.count (current_button)) { current_mode = NULL; } else { current_mode = modes[current_button]; if(current_mode != NULL) current_mode->SetAction(); } last_point = Point3f (0, 0, -1); last_track = track; } ////return center of trackball in Window coordinates. //Point3f Trackball::ScreenOrigin() { // return camera.Project(ModelOrigin()); //} //return center of trackball in Model coordinates //Point3f Trackball::ModelOrigin() { // return center; //} //Matrix44f Trackball::ScreenToModel() { // return camera.inverse; //} // //Similarityf Trackball::ModelToLocal() { // Similarityf m = local * last_track; // return m; //}