Heavily restructured. To be completed only rotation works...

This commit is contained in:
Paolo Cignoni 2004-06-09 14:01:13 +00:00
parent 68a6f52588
commit 782b814293
4 changed files with 192 additions and 81 deletions

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $Log: not supported by cvs2svn $
Revision 1.7 2004/05/14 03:15:09 ponchio
Redesigned partial version.
Revision 1.6 2004/05/12 20:55:18 ponchio Revision 1.6 2004/05/12 20:55:18 ponchio
*** empty log message *** *** empty log message ***
@ -41,7 +44,7 @@ Adding copyright.
****************************************************************************/ ****************************************************************************/
#include<gl/glew.h>
#include "trackball.h" #include "trackball.h"
#include <wrap/gl/math.h> #include <wrap/gl/math.h>
@ -111,7 +114,15 @@ void Trackball::GetView() {
} }
void Trackball::Apply() { void Trackball::Apply() {
glTranslate(center);
glMultMatrix(track.Matrix()); glMultMatrix(track.Matrix());
glTranslate(-center);
}
void Trackball::ApplyInverse() {
glTranslate(center);
glMultMatrix(track.InverseMatrix());
glTranslate(-center);
} }
/***************************************************************/ /***************************************************************/
@ -163,6 +174,15 @@ void Trackball::DrawPlaneHandle() {
} }
void Trackball::Draw() { void Trackball::Draw() {
glPushMatrix();
ApplyInverse();
glBegin(GL_POINTS);
for(int i=0;i<Hits.size();++i)
glVertex(Hits[i]);
glEnd();
glPopMatrix();
glPushMatrix(); glPushMatrix();
glTranslate(center); glTranslate(center);
@ -183,17 +203,15 @@ void Trackball::Draw() {
glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,amb); glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,amb);
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,col); glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,col);
glPushMatrix(); glPushMatrix();
DrawCircle();
glPushMatrix();
DrawCircle(); glRotatef(90,1,0,0);
glPushMatrix(); DrawCircle();
glRotatef(90,0,1,0);
glRotatef(90,1,0,0); DrawCircle();
DrawCircle();
glRotatef(90,0,1,0); glPopMatrix();
DrawCircle();
glPopMatrix();
glPopMatrix(); glPopMatrix();
glColor4f(1.0,.8f,.8f,1.0f); glColor4f(1.0,.8f,.8f,1.0f);
@ -249,10 +267,11 @@ void Trackball::Reset() {
} }
//interface //interface
void Trackball::MouseDown(int x, int y, Trackball::Button button) { void Trackball::MouseDown(int x, int y, int button) {
current_button |= button; current_button |= button;
SetCurrentAction(); SetCurrentAction();
last_point = Point3f((float)x, (float)y, 0); last_point = Point3f((float)x, (float)y, 0);
Hits.clear();
} }
void Trackball::MouseMove(int x, int y) { void Trackball::MouseMove(int x, int y) {
@ -264,7 +283,7 @@ void Trackball::MouseMove(int x, int y) {
current_mode->Apply(this, Point3f(float(x), float(y), 0)); current_mode->Apply(this, Point3f(float(x), float(y), 0));
} }
void Trackball::MouseUp(int /* x */, int /* y */, Trackball::Button button) { void Trackball::MouseUp(int /* x */, int /* y */, int button) {
current_button &= (~button); current_button &= (~button);
SetCurrentAction(); SetCurrentAction();
} }

View File

@ -25,6 +25,9 @@
History History
$Log: not supported by cvs2svn $ $Log: not supported by cvs2svn $
Revision 1.6 2004/05/14 03:15:09 ponchio
Redesigned partial version.
Revision 1.5 2004/05/12 20:55:18 ponchio Revision 1.5 2004/05/12 20:55:18 ponchio
*** empty log message *** *** empty log message ***
@ -47,17 +50,13 @@ Adding copyright.
#include <wrap/gui/view.h> #include <wrap/gui/view.h>
#include <wrap/gui/trackmode.h> #include <wrap/gui/trackmode.h>
#include <list> #include <list>
#include <vector>
#include <map> #include <map>
namespace vcg { namespace vcg {
/* A trackball stores two transformations /* A trackball stores a transformation called 'track' that effectively rotate the object.
the first one, local, is the one 'placing' the trackball somewhere, the rotation center, and size are kept in center and radius.
the second one, track, is the one that effectively rotate the object.
The 'local' transformation is the one that contains information about
the rotation center, the size and the orientation of the trackball.
the 'track' is the one implementing the effective transformation.
*/ */
class Transform { class Transform {
@ -97,6 +96,7 @@ namespace vcg {
//operating //operating
void GetView(); void GetView();
void Apply(); void Apply();
void ApplyInverse();
void Draw(); void Draw();
void ApplynDraw() { Apply(); Draw(); } void ApplynDraw() { Apply(); Draw(); }
void Reset(); void Reset();
@ -107,9 +107,9 @@ namespace vcg {
static void DrawPlaneHandle(); static void DrawPlaneHandle();
//interface //interface
void MouseDown(int x, int y, Button button); void MouseDown(int x, int y, /*Button*/ int button);
void MouseMove(int x, int y); void MouseMove(int x, int y);
void MouseUp(int x, int y, Button button); void MouseUp(int x, int y, /*Button */ int button);
void MouseWheel(Button notch); void MouseWheel(Button notch);
void ButtonUp(Button button); void ButtonUp(Button button);
void ButtonDown(Button button); void ButtonDown(Button button);
@ -147,15 +147,9 @@ namespace vcg {
}; };
///Find the current action ussing the current button
//protected: //protected:
View<float> camera; View<float> camera;
/* float ScreenRadius;
Point3f ScreenCenter;*/
void SetCurrentAction(); void SetCurrentAction();
int current_button; int current_button;
@ -166,6 +160,7 @@ namespace vcg {
Similarityf last_track; Similarityf last_track;
Similarityf last_view; Similarityf last_view;
Point3f last_point; Point3f last_point;
std::vector<Point3f> Hits;
bool dragging; bool dragging;
int button_mask; int button_mask;
@ -176,14 +171,6 @@ namespace vcg {
std::list<Transform> history; std::list<Transform> history;
int history_size; int history_size;
//Point3f ScreenOrigin(); //center of trackball in Screen coord
//Point3f ModelOrigin(); //center of trackball in Model coord
// Matrix44f ScreenToModel(); //forse non serve.....
// Similarityf ModelToLocal();
//Point3f ScreenToLocal(const Point3f &p);
//Point3f LocalToScreen(const Point3f &p);
friend class TrackMode; friend class TrackMode;
}; };

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $Log: not supported by cvs2svn $
Revision 1.5 2004/05/14 03:15:09 ponchio
Redesigned partial version.
Revision 1.4 2004/05/07 12:46:08 cignoni Revision 1.4 2004/05/07 12:46:08 cignoni
Restructured and adapted in a better way to opengl Restructured and adapted in a better way to opengl
@ -45,15 +48,20 @@ Adding copyright.
using namespace std; using namespace std;
using namespace vcg; using namespace vcg;
/// Compute the plane plane perpedicular to view dir and passing through manip center
Plane3f TrackMode::GetViewPlane(const View<float> &camera, Point3f center) { Plane3f TrackMode::GetViewPlane(const View<float> &camera, const Point3f &center) {
Point3f vp = camera.ViewPoint(); Point3f vp = camera.ViewPoint();
Plane3f pl; //plane perpedicular to view dir and passing through manip center Plane3f pl;
pl.Set(vp - center, (vp - center)*center); Point3f plnorm= vp - center;
plnorm.Normalize();
pl.Set(plnorm, plnorm*center);
return pl; return pl;
} }
/// Given a point p in window coordinate it compute the point where the lie p
/// over the plane paralell the viewplane and passing through the center of the trackball
Point3f TrackMode::HitViewPlane(Trackball *tb, const Point3f &p) { Point3f TrackMode::HitViewPlane(Trackball *tb, const Point3f &p) {
// plane perpedicular to view direction and passing through manip center // plane perpedicular to view direction and passing through manip center
Plane3f vp = GetViewPlane(tb->camera, tb->center); Plane3f vp = GetViewPlane(tb->camera, tb->center);
@ -65,14 +73,23 @@ Point3f TrackMode::HitViewPlane(Trackball *tb, const Point3f &p) {
return PonVP; return PonVP;
} }
// the most important function; given a new point in window coord, it update the transformation computed by the trackball.
// General scheme : the transformation is a function of just the begin and current mouse positions, with greater precision is function of just two 3d points over the manipulator.
void SphereMode::Apply(Trackball *tb, Point3f new_point) { void SphereMode::Apply(Trackball *tb, Point3f new_point) {
Point3f hitOld=Hit(tb, tb->last_point); Point3f hitOld=Hit(tb, tb->last_point);
Point3f hitNew=Hit(tb, new_point); Point3f hitNew=Hit(tb, new_point);
tb->Hits.push_back(hitNew);
Point3f axis = (hitNew- tb->center)^(hitOld- tb->center);
// Figure out how much to rotate around that axis.
//float phi=Angle((hitNew- tb->center),(hitOld- tb->center));
float phi = Distance(hitNew,hitOld) / tb->radius;
tb->track.rot = tb->last_track.rot * Quaternionf(phi,axis);
/* Codice Originale Ponchio
Point3f ref = (tb->camera.ViewPoint() - tb->center).Normalize(); Point3f ref = (tb->camera.ViewPoint() - tb->center).Normalize();
Point3f axis = hitNew^ref; Point3f axis = hitNew^ref;
axis.Normalize(); axis.Normalize();
float dist = (hitNew - ref).Norm()/2; float dist = (hitNew - ref).Norm()/2;
@ -88,9 +105,65 @@ void SphereMode::Apply(Trackball *tb, Point3f new_point) {
Quaternionf diff = r * Quaternionf(phi, axis) * Quaternionf diff = r * Quaternionf(phi, axis) *
Quaternionf(-ophi, oaxis) * Inverse(r); Quaternionf(-ophi, oaxis) * Inverse(r);
tb->track = Similarityf().SetRotate(diff) * tb->last_track; tb->track = Similarityf().SetRotate(diff) * tb->last_track;*/
} }
/*
dato un punto in coordinate di schermo e.g. in pixel stile opengl
calcola il punto di intersezione tra la viewline che passa per viewpoint e per hitplane e l'iperboloide.
l'iperboloide si assume essere quello di rotazione attorno alla retta viewpoint-center e di raggio rad
si assume come sistema di riferimento quello con l'origine su center ecome x la retta center-viewpoint
eq linea
hitplane.y
y = - ----------- * x + hitplane.y
viewpoint.x
eq hiperboloide di raggio r (e.g. che passa per (r/sqrt2,r/sqrt2)
1
y = --- * (r^2 /2.0)
x
hitplane.y
----------- * x^2 - hitplane.y *x + (r^2/2.0) == 0
viewpoint.x
*/
bool SphereMode::HitHyper(Point3f center, float radius, Point3f viewpoint, Plane3f vp, Point3f hitplane, Point3f &hit)
{
float hitplaney = Distance(center,hitplane);
float viewpointx= Distance(center,viewpoint);
float a = hitplaney/viewpointx;
float b = -hitplaney;
float c = radius*radius/2.0f;
float delta = b*b - 4*a*c;
float x1,x2,xval,yval;
if(delta>0)
{
x1= (- b - sqrt(delta))/(2.0*a);
x2= (- b + sqrt(delta))/(2.0*a);
xval=x1; // always take the minimum value solution
yval=c/xval; // alternatively it also oould be the other part of the equation yval=-(hitplaney/viewpointx)*xval+hitplaney;
}
else
{
return false;
}
// Computing the result in 3d space;
Point3f dirRadial=hitplane-center;
dirRadial.Normalize();
Point3f dirView=vp.Direction();
dirView.Normalize();
hit= center +dirRadial*yval+dirView*xval;
return true;
}
/* dato un punto in coordinate di schermo e.g. in pixel stile opengl /* dato un punto in coordinate di schermo e.g. in pixel stile opengl
restituisce un punto in coordinate di mondo sulla superficie restituisce un punto in coordinate di mondo sulla superficie
della trackball. della trackball.
@ -101,45 +174,76 @@ void SphereMode::Apply(Trackball *tb, Point3f new_point) {
X 0 sqrt(1/2) 1 X 0 sqrt(1/2) 1
eq sfera: y=sqrt(1-x*x); 1 sqrt(1/2) 0 eq sfera: y=sqrt(1-x*x); 1 sqrt(1/2) 0
eq iperboloide : y=1/2x; inf sqrt(1/2) 1/2 eq iperboloide : y=1/2*x; inf sqrt(1/2) 1/2
eq cono y=x+sqrt(2); eq cono y=x+sqrt(2);
*/ */
Point3f SphereMode::Hit(Trackball *tb, const Point3f &p) { Point3f SphereMode::Hit(Trackball *tb, const Point3f &p) {
const float Thr = tb->radius/math::Sqrt(2.0f); const float Thr = tb->radius/math::Sqrt(2.0f);
Line3fN vn = tb->camera.ViewLineFromModel(tb->center); Line3fN vn = tb->camera.ViewLineFromModel(tb->center);
Line3fN ln = tb->camera.ViewLineFromWindow(Point3f(p[0],p[1],0)); Line3fN ln = tb->camera.ViewLineFromWindow(Point3f(p[0],p[1],0));
Point3f viewpoint = tb->camera.ViewPoint(); Point3f viewpoint = tb->camera.ViewPoint();
Plane3f vp = GetViewPlane(tb->camera, tb->center); Plane3f vp = GetViewPlane(tb->camera, tb->center);
vp.SetOffset(vp.Offset() + Thr); Point3f hit,hitPlane,hitSphere,hitSphere1,hitSphere2,hitHyper;
Intersection<float>(vp, ln, hitPlane);
Sphere3f sphere(tb->center,tb->radius);
bool resSp = Intersection<float>(sphere, ln, hitSphere1, hitSphere2);
if(Distance(viewpoint,hitSphere1)<Distance(viewpoint,hitSphere2))
hitSphere=hitSphere1;
else hitSphere=hitSphere2;
Point3f hit; float dl=Distance(ln,tb->center);
bool res = Intersection<float>(vp, ln, hit); bool resHp = HitHyper(tb->center, tb->radius, viewpoint, vp, hitPlane, hitHyper) ;
float d = Distance(tb->center - vn.Direction()*Thr, hit);
if(d < Thr) {
Point3f hit2;
Sphere3f sphere(tb->center, tb->radius);
bool res = Intersection<float>(sphere, ln, hit, hit2);
//find closest intersection to sphere // four cases
float d = (hit - viewpoint).Norm();
float d2 = (hit2 - viewpoint).Norm(); // 1) Degenerate line tangent to both sphere and hyperboloid!
if(d > d2) hit = hit2; if((!resSp && !resHp) )
hit -= tb->center; {
} else { hit=ClosestPoint(ln,tb->center);
if(d > 2.99 * Thr) //printf("closest point to line %f\n",Distance(hit,tb->center));
d = 2.99 * Thr; return hit;
Point3f norm = (hit - tb->center)^(viewpoint - tb->center);
norm.Normalize();
float phi = -M_PI/4 - 3*M_PI/8 *(d - Thr)/Thr;
Quaternionf q(phi, norm);
hit = q.Rotate((viewpoint - tb->center).Normalize() * tb->radius);
} }
hit.Normalize(); if((resSp && !resHp) ) return hitSphere; // 2) line cross only the sphere
return hit; if((!resSp && resHp) ) return hitHyper; // 3) line cross only the hyperboloid
// 4) line cross both sphere and hyperboloid: choose according angle.
float angleDeg=math::ToDeg(Angle((viewpoint-tb->center),(hitSphere-tb->center)));
//printf("Angle %f (%5.2f %5.2f %5.2f) (%5.2f %5.2f %5.2f)\n",angleDeg,hitSphere[0],hitSphere[1],hitSphere[2],hitHyper[0],hitHyper[1],hitHyper[2]);
if(angleDeg<45) return hitSphere;
else return hitHyper;
//
// Codice ORIGINALE PONCHIO
//vp.SetOffset(vp.Offset() + Thr);
//Point3f hit;
//bool res = Intersection<float>(vp, ln, hit);
//float d = Distance(tb->center - vn.Direction()*Thr, hit);
//if(d < Thr) {
// Point3f hit2;
// Sphere3f sphere(tb->center, tb->radius);
// bool res = Intersection<float>(sphere, ln, hit, hit2);
// //find closest intersection to sphere
// float d = (hit - viewpoint).Norm();
// float d2 = (hit2 - viewpoint).Norm();
// if(d > d2) hit = hit2;
// hit -= tb->center;
//} else {
// if(d > 2.99 * Thr)
// d = 2.99 * Thr;
// Point3f norm = (hit - tb->center)^(viewpoint - tb->center);
// norm.Normalize();
// float phi = -M_PI/4 - 3*M_PI/8 *(d - Thr)/Thr;
// Quaternionf q(phi, norm);
// hit = q.Rotate((viewpoint - tb->center).Normalize() * tb->radius);
//}
// hit.Normalize();
// return hit;
} }
void PlaneMode::Apply(Trackball *tb, Point3f new_point) { void PlaneMode::Apply(Trackball *tb, Point3f new_point) {

View File

@ -24,6 +24,9 @@
History History
$Log: not supported by cvs2svn $ $Log: not supported by cvs2svn $
Revision 1.5 2004/05/14 03:15:09 ponchio
Redesigned partial version.
Revision 1.4 2004/05/07 12:46:08 cignoni Revision 1.4 2004/05/07 12:46:08 cignoni
Restructured and adapted in a better way to opengl Restructured and adapted in a better way to opengl
@ -52,12 +55,8 @@ public:
virtual ~TrackMode() {} virtual ~TrackMode() {}
virtual void Apply(Trackball *trackball, Point3f new_point) = 0; virtual void Apply(Trackball *trackball, Point3f new_point) = 0;
virtual void Draw() {} virtual void Draw() {}
//virtual void Draw() {}
// virtual Similarityf ComputeFromWindow(const Point3f &old_point,
//const Point3f &new_point) = 0;
// Point3f Hit(const Point3f &p);
protected: protected:
Plane3f GetViewPlane(const View<float> &view, Point3f center); Plane3f GetViewPlane(const View<float> &view, const Point3f &center);
Point3f HitViewPlane(Trackball *trackball, const Point3f &p); Point3f HitViewPlane(Trackball *trackball, const Point3f &p);
}; };
@ -68,12 +67,14 @@ class SphereMode: public TrackMode {
void Apply(Trackball *trackball, Point3f new_point); void Apply(Trackball *trackball, Point3f new_point);
protected: protected:
Point3f Hit(Trackball *trackball, const Point3f &p); Point3f Hit(Trackball *trackball, const Point3f &p);
bool HitHyper(Point3f center, float radius, Point3f viewpoint, Plane3f vp, Point3f hitplane, Point3f &hit) ;
}; };
class CylinderMode: public TrackMode { class CylinderMode: public TrackMode {
public: public:
CylinderMode(const Line3f &line, float radius = 1) {} CylinderMode(const Line3f &/*line*/, float /*radius = 1*/) {}
void Apply(Trackball *trackball, Point3f new_point) {} void Apply(Trackball * /*trackball*/, Point3f /*new_point*/) {}
protected: protected:
Line3f line; Line3f line;
float radius; float radius;
@ -89,15 +90,15 @@ protected:
class LineMode: public TrackMode { class LineMode: public TrackMode {
public: public:
LineMode(const Line3f &line) {} LineMode(const Line3f &/*line*/) {}
void Apply(Trackball *trackball, Point3f new_point) {} void Apply(Trackball * /*trackball*/, Point3f /*new_point*/) {}
protected: protected:
Line3f line; Line3f line;
}; };
class ScaleMode: public TrackMode { class ScaleMode: public TrackMode {
public: public:
void Apply(Trackball *trackball, Point3f new_point) {} void Apply(Trackball * /*trackball*/, Point3f /*new_point*/) {}
}; };
}//namespace }//namespace