vcglib/wrap/gui/trackball.cpp

363 lines
9.5 KiB
C++

/****************************************************************************
* 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.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 <gl... -> #include <GL...
Revision 1.9 2004/07/11 22:06:55 cignoni
Added scaling by wheel
Revision 1.8 2004/06/09 14:01:13 cignoni
Heavily restructured. To be completed only rotation works...
Revision 1.7 2004/05/14 03:15:09 ponchio
Redesigned partial version.
Revision 1.6 2004/05/12 20:55:18 ponchio
*** empty log message ***
Revision 1.5 2004/05/07 12:46:08 cignoni
Restructured and adapted in a better way to opengl
Revision 1.4 2004/04/07 10:54:10 cignoni
Commented out unused parameter names and other minor warning related issues
Revision 1.3 2004/03/31 15:08:03 ponchio
Fixed current_action initialization.
Revision 1.2 2004/03/25 14:55:25 ponchio
Adding copyright.
****************************************************************************/
#include <GL/glew.h>
#include "trackball.h"
#include <wrap/gl/math.h>
#include <wrap/gl/space.h>
using namespace vcg;
#include <iostream> //debug!
using namespace std;
Transform::Transform() {
track.SetIdentity();
radius=1.0f;
center=Point3f(0,0,0);
}
Trackball::Trackball(): current_button(0), current_mode(NULL),
dragging(false), spinnable(true), spinning(false),
history_size(10) {
//here we add mode
modes[0] = NULL;
modes[BUTTON_LEFT] = new SphereMode();
modes[BUTTON_LEFT | KEY_CTRL] = new PlaneMode(Plane3f(0, Point3f(1, 0, 0)));
modes[BUTTON_LEFT | KEY_SHIFT] = new ScaleMode();
modes[BUTTON_LEFT | KEY_ALT ] = new ZMode();
modes[WHEEL] = new ScaleMode();
SetCurrentAction();
}
Trackball::~Trackball() {
map<int, TrackMode *>::iterator i;
//for(i = modes.begin(); i != modes.end(); i++)
// delete (*i).second;
}
void Trackball::SetIdentity() {
track.SetIdentity();
Reset();
}
void Trackball::SetPosition(const Point3f &c, int /* millisec */) {
center = c;
}
void Trackball::GetView() {
camera.GetView();
}
void Trackball::DrawPostApply() {
glPushMatrix();
glTranslate(center);
glMultMatrix(track.InverseMatrix());
Matrix44f r;
track.rot.ToMatrix(r);
glMultMatrix(r);
DrawIcon();
glTranslate(-center);
glMultMatrix(track.Matrix());
}
void Trackball::Apply(bool ToDraw) {
glTranslate(center);
if(ToDraw)
{
if(DH.DrawTrack) {
glBegin(GL_LINE_STRIP);
for(vector<Point3f>::iterator vi=Hits.begin();vi!=Hits.end();++vi)
glVertex(*vi);
glEnd();
}
glPushMatrix();
Matrix44f r;
track.rot.ToMatrix(r);
glMultMatrix(r);
DrawIcon();
glPopMatrix();
}
glMultMatrix(track.Matrix());
glTranslate(-center);
}
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;;
}
/***************************************************************/
void Trackball::DrawCircle() {
int nside=DH.CircleStep;
const double pi2=3.14159265*2.0;
glBegin(GL_LINE_LOOP);
for(double i=0;i<nside;i++){
glNormal3d(cos(i*pi2/nside), sin(i*pi2/nside), 0.0);
glVertex3d(cos(i*pi2/nside), sin(i*pi2/nside), 0.0);
}
glEnd();
DrawPlaneHandle();
}
void Trackball::DrawPlane() {
const int nl=10;
float w=5.0f/3.0f;
float u;
glBegin(GL_LINES);
glNormal3f(0.0,0.0,1.0);
for( u=-w; u<=w+0.01f; u+=2*w/nl){
glVertex3f(-w, +u, 0);
glVertex3f(+w, +u, 0);
glVertex3f(+u, -w, 0);
glVertex3f(+u, +w, 0);
}
glEnd();
}
void Trackball::DrawPlaneHandle() {
float r=1.0;
float dr=r/10.0f;
glBegin(GL_LINE_STRIP);
glVertex3f(+r+dr, +r, 0.0);
glVertex3f(+r , +r+dr,0.0);
glVertex3f(+r-dr, +r, 0.0);
glVertex3f(+r , +r-dr,0.0);
glVertex3f(+r+dr, +r, 0.0);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f(-r+dr, -r, 0.0);
glVertex3f(-r , -r+dr,0.0);
glVertex3f(-r-dr, -r, 0.0);
glVertex3f(-r , -r-dr,0.0);
glVertex3f(-r+dr, -r, 0.0);
glEnd();
}
void Trackball::DrawIcon() {
glPushMatrix();
glScale(radius);
/// Here start the real drawing stuff
float amb[4] ={.3f,.3f,.3f,1.0f};
float col[4] ={.5f,.5f,.8f,1.0f};
//float col2[4]={.9f,.9f,1.0f,1.0f};
glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT);
if(current_mode == NULL ) glLineWidth(DH.LineWidthStill);
else glLineWidth(DH.LineWidthMoving);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor(DH.color);
glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,amb);
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,col);
glPushMatrix();
DrawCircle();
glPushMatrix();
glRotatef(90,1,0,0);
DrawCircle();
glRotatef(90,0,1,0);
DrawCircle();
glPopMatrix();
glPopMatrix();
//glColor4f(1.0,.8f,.8f,1.0f);
glPopAttrib();
glPopMatrix();
}
void Trackball::Reset() {
track.SetIdentity();
}
//interface
void Trackball::MouseDown(int button) {
current_button |= button;
SetCurrentAction();
Hits.clear();
}
void Trackball::MouseDown(int x, int y, int button) {
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;
}
current_mode->Apply(this, Point3f(float(x), float(y), 0));
}
void Trackball::MouseUp(int /* x */, int /* y */, int button) {
current_button &= (~button);
SetCurrentAction();
}
// it assumes that a notch of 1.0 is a single step of the wheel
void Trackball::MouseWheel(float notch ) {
if(current_mode == NULL)
{
SphereMode tm;
tm.TrackMode::Apply(this, notch);
} else
current_mode->Apply(this, notch);
}
void Trackball::ButtonDown(Trackball::Button button) {
current_button |= button;
SetCurrentAction();
}
void Trackball::ButtonUp(Trackball::Button button) {
current_button &= (~button);
SetCurrentAction();
}
//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;
}
//interfaccia navigation:
void Trackball::Back(){}
void Trackball::Forward(){}
void Trackball::Home(){}
void Trackball::HistorySize(int /* lenght */){}
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];
last_point = Point3f(0, 0, -1);
last_track = track;
// last_view = view;
}
////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;
//}