From 782b81429391d54ad843ea026eb98322beda6da6 Mon Sep 17 00:00:00 2001 From: cignoni Date: Wed, 9 Jun 2004 14:01:13 +0000 Subject: [PATCH] Heavily restructured. To be completed only rotation works... --- wrap/gui/trackball.cpp | 45 +++++++---- wrap/gui/trackball.h | 35 +++------ wrap/gui/trackmode.cpp | 172 +++++++++++++++++++++++++++++++++-------- wrap/gui/trackmode.h | 21 ++--- 4 files changed, 192 insertions(+), 81 deletions(-) diff --git a/wrap/gui/trackball.cpp b/wrap/gui/trackball.cpp index 4c4f4572..59d9fe5b 100644 --- a/wrap/gui/trackball.cpp +++ b/wrap/gui/trackball.cpp @@ -24,6 +24,9 @@ History $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 *** empty log message *** @@ -41,7 +44,7 @@ Adding copyright. ****************************************************************************/ - +#include #include "trackball.h" #include @@ -111,7 +114,15 @@ void Trackball::GetView() { } void Trackball::Apply() { + glTranslate(center); 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() { + + glPushMatrix(); + ApplyInverse(); + glBegin(GL_POINTS); + for(int i=0;iApply(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); SetCurrentAction(); } diff --git a/wrap/gui/trackball.h b/wrap/gui/trackball.h index b378851a..e70b4791 100644 --- a/wrap/gui/trackball.h +++ b/wrap/gui/trackball.h @@ -25,6 +25,9 @@ History $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 *** empty log message *** @@ -47,17 +50,13 @@ Adding copyright. #include #include #include +#include #include namespace vcg { - /* A trackball stores two transformations - the first one, local, is the one 'placing' the trackball somewhere, - 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. - + /* A trackball stores a transformation called 'track' that effectively rotate the object. + the rotation center, and size are kept in center and radius. + */ class Transform { @@ -97,6 +96,7 @@ namespace vcg { //operating void GetView(); void Apply(); + void ApplyInverse(); void Draw(); void ApplynDraw() { Apply(); Draw(); } void Reset(); @@ -107,9 +107,9 @@ namespace vcg { static void DrawPlaneHandle(); //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 MouseUp(int x, int y, Button button); + void MouseUp(int x, int y, /*Button */ int button); void MouseWheel(Button notch); void ButtonUp(Button button); void ButtonDown(Button button); @@ -147,15 +147,9 @@ namespace vcg { }; - ///Find the current action ussing the current button - - //protected: View camera; - /* float ScreenRadius; - Point3f ScreenCenter;*/ - void SetCurrentAction(); int current_button; @@ -166,6 +160,7 @@ namespace vcg { Similarityf last_track; Similarityf last_view; Point3f last_point; + std::vector Hits; bool dragging; int button_mask; @@ -176,14 +171,6 @@ namespace vcg { std::list history; 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; }; diff --git a/wrap/gui/trackmode.cpp b/wrap/gui/trackmode.cpp index 0b64d7d7..6f5b15a2 100644 --- a/wrap/gui/trackmode.cpp +++ b/wrap/gui/trackmode.cpp @@ -24,6 +24,9 @@ History $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 Restructured and adapted in a better way to opengl @@ -45,15 +48,20 @@ Adding copyright. using namespace std; using namespace vcg; - -Plane3f TrackMode::GetViewPlane(const View &camera, Point3f center) { +/// Compute the plane plane perpedicular to view dir and passing through manip center +Plane3f TrackMode::GetViewPlane(const View &camera, const Point3f ¢er) { Point3f vp = camera.ViewPoint(); - Plane3f pl; //plane perpedicular to view dir and passing through manip center - pl.Set(vp - center, (vp - center)*center); + Plane3f pl; + Point3f plnorm= vp - center; + plnorm.Normalize(); + pl.Set(plnorm, plnorm*center); 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) { // plane perpedicular to view direction and passing through manip center Plane3f vp = GetViewPlane(tb->camera, tb->center); @@ -65,14 +73,23 @@ Point3f TrackMode::HitViewPlane(Trackball *tb, const Point3f &p) { 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) { Point3f hitOld=Hit(tb, tb->last_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 axis = hitNew^ref; axis.Normalize(); 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(-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 restituisce un punto in coordinate di mondo sulla superficie della trackball. @@ -101,45 +174,76 @@ void SphereMode::Apply(Trackball *tb, Point3f new_point) { X 0 sqrt(1/2) 1 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); */ Point3f SphereMode::Hit(Trackball *tb, const Point3f &p) { const float Thr = tb->radius/math::Sqrt(2.0f); + Line3fN vn = tb->camera.ViewLineFromModel(tb->center); Line3fN ln = tb->camera.ViewLineFromWindow(Point3f(p[0],p[1],0)); Point3f viewpoint = tb->camera.ViewPoint(); - Plane3f vp = GetViewPlane(tb->camera, tb->center); - vp.SetOffset(vp.Offset() + Thr); + Point3f hit,hitPlane,hitSphere,hitSphere1,hitSphere2,hitHyper; + Intersection(vp, ln, hitPlane); + Sphere3f sphere(tb->center,tb->radius); + bool resSp = Intersection(sphere, ln, hitSphere1, hitSphere2); + if(Distance(viewpoint,hitSphere1)(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(sphere, ln, hit, hit2); + float dl=Distance(ln,tb->center); + bool resHp = HitHyper(tb->center, tb->radius, viewpoint, vp, hitPlane, hitHyper) ; - //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); + // four cases + + // 1) Degenerate line tangent to both sphere and hyperboloid! + if((!resSp && !resHp) ) + { + hit=ClosestPoint(ln,tb->center); + //printf("closest point to line %f\n",Distance(hit,tb->center)); + return hit; } - hit.Normalize(); - return hit; + if((resSp && !resHp) ) return hitSphere; // 2) line cross only the sphere + 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(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(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) { diff --git a/wrap/gui/trackmode.h b/wrap/gui/trackmode.h index 27e6ed12..8fa50812 100644 --- a/wrap/gui/trackmode.h +++ b/wrap/gui/trackmode.h @@ -24,6 +24,9 @@ History $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 Restructured and adapted in a better way to opengl @@ -52,12 +55,8 @@ public: virtual ~TrackMode() {} virtual void Apply(Trackball *trackball, Point3f new_point) = 0; virtual void Draw() {} - //virtual void Draw() {} - // virtual Similarityf ComputeFromWindow(const Point3f &old_point, - //const Point3f &new_point) = 0; - // Point3f Hit(const Point3f &p); protected: - Plane3f GetViewPlane(const View &view, Point3f center); + Plane3f GetViewPlane(const View &view, const Point3f ¢er); Point3f HitViewPlane(Trackball *trackball, const Point3f &p); }; @@ -68,12 +67,14 @@ class SphereMode: public TrackMode { void Apply(Trackball *trackball, Point3f new_point); protected: 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 { public: - CylinderMode(const Line3f &line, float radius = 1) {} - void Apply(Trackball *trackball, Point3f new_point) {} + CylinderMode(const Line3f &/*line*/, float /*radius = 1*/) {} + void Apply(Trackball * /*trackball*/, Point3f /*new_point*/) {} protected: Line3f line; float radius; @@ -89,15 +90,15 @@ protected: class LineMode: public TrackMode { public: - LineMode(const Line3f &line) {} - void Apply(Trackball *trackball, Point3f new_point) {} + LineMode(const Line3f &/*line*/) {} + void Apply(Trackball * /*trackball*/, Point3f /*new_point*/) {} protected: Line3f line; }; class ScaleMode: public TrackMode { public: - void Apply(Trackball *trackball, Point3f new_point) {} + void Apply(Trackball * /*trackball*/, Point3f /*new_point*/) {} }; }//namespace