From 1ff3a301ec7a8cffbc343c520a7867f1a9ce32f4 Mon Sep 17 00:00:00 2001 From: cignoni Date: Tue, 4 Nov 2014 23:16:04 +0000 Subject: [PATCH] Trackball Improvement. Now it works well also for ortho views --- wrap/gui/trackmode.cpp | 352 +++++++++++++++++++++-------------------- wrap/gui/trackutils.h | 148 ++++++----------- wrap/gui/view.h | 51 ++++-- 3 files changed, 266 insertions(+), 285 deletions(-) diff --git a/wrap/gui/trackmode.cpp b/wrap/gui/trackmode.cpp index 7c5f39bc..ad8bfd5f 100644 --- a/wrap/gui/trackmode.cpp +++ b/wrap/gui/trackmode.cpp @@ -8,7 +8,7 @@ * \ * * All rights reserved. * * * -* This program is free software; you can redistribute it and/or modify * +* 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. * @@ -41,8 +41,8 @@ void TrackMode::SetAction (){} void TrackMode::Reset (){} -bool TrackMode::IsAnimating(const Trackball *){ - return false; +bool TrackMode::IsAnimating(const Trackball *){ + return false; } void TrackMode::Animate(unsigned int, Trackball *){ @@ -58,12 +58,12 @@ void TrackMode::Undo(){} void InactiveMode::Draw(Trackball * tb){ DrawSphereIcon(tb,false); } - + // Sphere mode implementation. // 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 +// 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) { @@ -72,9 +72,13 @@ void SphereMode::Apply (Trackball * tb, Point3f new_point) tb->Hits.push_back (hitNew); Point3f center = tb->center; Point3f axis = (hitNew - center) ^ (hitOld - center); + vcg::Normalize(axis); + // Figure out how much to rotate around that axis. - float phi = Distance (hitNew, hitOld) / tb->radius; -// tb->track.rot = tb->last_track.rot * Quaternionf (-phi, axis); +// float phi = Distance (hitNew, hitOld) / tb->radius; +// float phi = vcg::Angle(hitNew - center,hitOld - center)*(Distance(hitNew,center)/tb->radius); + float phi = max(vcg::Angle(hitNew - center,hitOld - center),(Distance(hitNew,hitOld)/tb->radius)) ; + tb->track.rot = Quaternionf (-phi, axis) * tb->last_track.rot; } @@ -120,7 +124,7 @@ void ScaleMode::Apply (Trackball * tb, float WheelNotch) { tb->track.sca *= pow (1.2f, -WheelNotch); } - + void ScaleMode::Apply (Trackball * tb, Point3f new_point) { tb->track.sca = tb->last_track.sca * pow (3.0f, -(getDeltaY(tb,new_point))); @@ -157,7 +161,7 @@ void PlaneMode::Apply (Trackball * tb, Point3f new_point) std::pair< Point3f, bool > hitOld = HitPlane(tb,tb->last_point,plane); std::pair< Point3f, bool > hitNew = HitPlane(tb,new_point,plane); if(hitOld.second && hitNew.second){ - tb->Translate (hitNew.first - hitOld.first); + tb->Translate (hitNew.first - hitOld.first); } } @@ -170,7 +174,7 @@ void PlaneMode::Draw(Trackball * tb){ void CylinderMode::Apply (Trackball * tb, float WheelNotch) { const float PI2=6.283185307179586232f; - float angle= (snap==0.0) ? WheelNotch/(tb->radius * PI2) : WheelNotch * snap; + float angle= (snap==0.0) ? WheelNotch/(tb->radius * PI2) : WheelNotch * snap; tb->track.rot = tb->last_track.rot * Quaternionf (angle,axis.Direction()); } @@ -182,12 +186,12 @@ void CylinderMode::Apply (Trackball * tb, Point3f new_point) float angle; const float EPSILON=0.005f; // this IS scale independent if(axisproj.Direction().Norm() < EPSILON){ - angle=(10.0f * getDeltaY(tb,new_point)) / tb->radius; + angle=(10.0f * getDeltaY(tb,new_point)) / tb->radius; } else { Point3f hitOld = HitViewPlane (tb, tb->last_point); Point3f hitNew = HitViewPlane (tb, new_point); axisproj.Normalize(); - Point3f plusdir= viewplane.Direction() ^ axisproj.Direction(); + Point3f plusdir= viewplane.Direction() ^ axisproj.Direction(); float distOld = signedDistance(axisproj,hitOld,plusdir); float distNew = signedDistance(axisproj,hitNew,plusdir); angle= (distNew-distOld) / tb->radius; @@ -239,31 +243,31 @@ Point3f PathMode::SetStartNear(Point3f point) Point3f p0,p1; float nearest_state=0; Point3f nearest_point=points[0]; - float nearest_distance=Distance(nearest_point,point); + float nearest_distance=Distance(nearest_point,point); unsigned int npts = int(points.size()); for(unsigned int i = 1;i <= npts;i++){ - if( i == npts){ - if (wrap){ - p0=points[npts-1]; - p1=points[0]; - } else { - break; - } - } else { - p0=points[i-1]; - p1=points[i]; - } + if( i == npts){ + if (wrap){ + p0=points[npts-1]; + p1=points[0]; + } else { + break; + } + } else { + p0=points[i-1]; + p1=points[i]; + } //Point3f segment_point=ClosestPoint(Segment3f(p0,p1),point); - Point3f segment_point; - float distance; - vcg::SegmentPointDistance(Segment3f(p0,p1),point,segment_point,distance); - // float distance=Distance(segment_point,point); + Point3f segment_point; + float distance; + vcg::SegmentPointDistance(Segment3f(p0,p1),point,segment_point,distance); + // float distance=Distance(segment_point,point); if(distance= 0.0 ); @@ -278,22 +282,22 @@ Point3f PathMode::SetStartNear(Point3f point) void PathMode::GetPoints(float state, Point3f & point, Point3f & prev_point, Point3f & next_point) { assert(state >= 0.0f); - assert(state <= 1.0f); - float remaining_norm=state; + assert(state <= 1.0f); + float remaining_norm=state; Point3f p0(0,0,0),p1(0,0,0); unsigned int npts = int(points.size()); for(unsigned int i = 1;i <= npts;i++){ - if( i == npts){ - if (wrap){ - p0=points[npts-1]; - p1=points[0]; - } else { - break; - } - } else { - p0=points[i-1]; - p1=points[i]; - } + if( i == npts){ + if (wrap){ + p0=points[npts-1]; + p1=points[0]; + } else { + break; + } + } else { + p0=points[i-1]; + p1=points[i]; + } float segment_norm= Distance(p0,p1) / path_length; if (segment_norm < remaining_norm){ remaining_norm -= segment_norm; @@ -303,28 +307,28 @@ void PathMode::GetPoints(float state, Point3f & point, Point3f & prev_point, Poi next_point = p1; float ratio= remaining_norm / segment_norm; point = prev_point + (( next_point - prev_point ) * ratio); - const float EPSILON=min_seg_length * 0.01f; + const float EPSILON=min_seg_length * 0.01f; if(Distance(point,prev_point) < EPSILON){ point=prev_point; if (i > 1){ - prev_point=points[i-2]; + prev_point=points[i-2]; } else if (wrap){ prev_point=points[npts-1]; - } + } } else if (Distance(point,next_point) < EPSILON){ point=next_point; if( i < (npts-1)){ - next_point=points[i+1]; + next_point=points[i+1]; } else { - if (wrap){ - next_point=points[1]; - } else { - next_point=points[npts-1]; - } - } + if (wrap){ + next_point=points[1]; + } else { + next_point=points[npts-1]; + } + } } return; - } + } // rounding errors can lead out of the for.. prev_point = p0; point = p1; @@ -346,7 +350,7 @@ void PathMode::Apply (Trackball * tb, float WheelNotch) GetPoints(current_state,old_point,prev_point,next_point); current_state=Normalize(current_state+delta); GetPoints(current_state,new_point,prev_point,next_point); - tb->Translate (new_point - old_point); + tb->Translate (new_point - old_point); } float PathMode::Normalize(float state) @@ -360,9 +364,9 @@ float PathMode::Normalize(float state) return fractpart; } if ( state < 0.0f ) - return 0.0f; + return 0.0f; if ( state > 1.0f ) - return 1.0f; + return 1.0f; return state; } @@ -401,7 +405,7 @@ float PathMode::HitPoint(float state, Ray3fN ray, Point3f &hit_point) { Point3f current_point, next_point, prev_point; GetPoints(state,current_point,prev_point,next_point); - + Point3f closest_point; closest_point=ray.ClosestPoint(current_point); int verse=Verse(closest_point,current_point,prev_point,next_point); @@ -409,26 +413,26 @@ float PathMode::HitPoint(float state, Ray3fN ray, Point3f &hit_point) hit_point=current_point; return 0.0f; } - + Segment3f active_segment; if (verse > 0){ - active_segment=Segment3f(current_point,next_point); + active_segment=Segment3f(current_point,next_point); } else { active_segment= Segment3f(current_point,prev_point); - } + } //hit_point=ClosestPoint(active_segment,closest_point); - float dist; - vcg::SegmentPointDistance(active_segment,closest_point,hit_point,dist); + float dist; + vcg::SegmentPointDistance(active_segment,closest_point,hit_point,dist); return verse * ((hit_point-current_point).Norm() / path_length); -} +} void PathMode::SetAction (){ - Point3f temp1,temp2; + Point3f temp1,temp2; GetPoints(current_state,old_hitpoint,temp1,temp2); } - + void PathMode::Apply (Trackball * tb, Point3f new_point) { undo_current_state=current_state; @@ -462,7 +466,7 @@ void PathMode::Draw(Trackball * tb){ void AreaMode::Init(const std::vector < Point3f > &pts) { unsigned int npts = int(pts.size()); - + assert(npts >= 3); //get the plane Point3f p0=pts[0]; @@ -471,38 +475,38 @@ void AreaMode::Init(const std::vector < Point3f > &pts) bool pts_not_in_line=false; Point3f a,b; for(unsigned int i=0;i EPSILON; if(pts_not_in_line){ - plane.Init( pts[i%npts], - pts[(i+(onethird))%npts], + plane.Init( pts[i%npts], + pts[(i+(onethird))%npts], pts[(i+(2*onethird))%npts]); - break; + break; } } - assert(pts_not_in_line); + assert(pts_not_in_line); float ncx,ncy,ncz; ncx=fabs(plane.Direction()[0]); ncy=fabs(plane.Direction()[1]); - ncz=fabs(plane.Direction()[2]); + ncz=fabs(plane.Direction()[2]); if(( ncx > ncy ) && ( ncx > ncz )){ first_coord_kept=1; second_coord_kept=2; } else if(( ncy > ncx ) && ( ncy > ncz)){ first_coord_kept=0; second_coord_kept=2; - } else { + } else { first_coord_kept=0; second_coord_kept=1; } - points.reserve(npts); + points.reserve(npts); for(unsigned int i=0;icamera.Project(status)-new_point; - begin_action=false; - } + delta_mouse=tb->camera.Project(status)-new_point; + begin_action=false; + } std::pair< Point3f, bool > hitNew = HitPlane(tb,new_point+delta_mouse,plane); if(! hitNew.second){ - return; + return; } - Point3f hit_point=hitNew.first; + Point3f hit_point=hitNew.first; Point3f delta_status=Move(status,hit_point); status += delta_status; - tb->Translate (status - old_status); + tb->Translate (status - old_status); rubberband_handle=hit_point; } void AreaMode::SetAction () { - begin_action=true; + begin_action=true; old_status=status; - + path.clear(); path.push_back(status); rubberband_handle=status; @@ -555,44 +559,44 @@ Point3f AreaMode::Move(Point3f start,Point3f end) bool done=false; bool end_inside=Inside(end); while(!done){ - path.push_back(pt); + path.push_back(pt); Segment3f segment(pt,end); bool p_on_side = false; bool hit=false; - + Point3f pside(0,0,0),phit(0,0,0); bool slide=false,mid_inside=false; - + int np = int(points.size()), i, j; for (i = 0, j = np-1; i < np; j = i++) { Segment3f side(points[i],points[j]); Point3f pseg,psid; //std::pair res=SegmentSegmentDistance(segment,side,pseg,psid); - std::pair res; - vcg::SegmentSegmentDistance(segment,side,res.first,res.second,pseg,psid); + std::pair res; + vcg::SegmentSegmentDistance(segment,side,res.first,res.second,pseg,psid); if(res.first < EPSILON && ! res.second){ - float dist= Distance(pt,pseg); - if(dist < EPSILON){ + float dist= Distance(pt,pseg); + if(dist < EPSILON){ //Point3f pn=ClosestPoint(side,end); - Point3f pn; - float dist; - vcg::SegmentPointDistance(side,end,pn,dist); + Point3f pn; + float dist; + vcg::SegmentPointDistance(side,end,pn,dist); if(!p_on_side || (Distance(pn,end) EPSILON; - - if (hit) + + if (hit) mid_inside = Inside( pt + ( ( phit - pt ) / 2) ); if ( !hit && end_inside ){ @@ -600,16 +604,16 @@ Point3f AreaMode::Move(Point3f start,Point3f end) done = true; } else if ( hit && (!p_on_side || (p_on_side && mid_inside))) { pt = phit; - } else if ( p_on_side && slide) { + } else if ( p_on_side && slide) { pt = pside; } else { done = true; - } + } } - path.push_back(pt); + path.push_back(pt); return pt - start; } - + // adapted from the original C code by W. Randolph Franklin // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html bool AreaMode::Inside(Point3f point) @@ -620,15 +624,15 @@ bool AreaMode::Inside(Point3f point) float yi, yj, xi, xj; int i, j, np=int(points.size()); for (i = 0, j = np-1; i < np; j = i++) { - xi=points[i][first_coord_kept]; - yi=points[i][second_coord_kept]; - xj=points[j][first_coord_kept]; - yj=points[j][second_coord_kept]; + xi=points[i][first_coord_kept]; + yi=points[i][second_coord_kept]; + xj=points[j][first_coord_kept]; + yj=points[j][second_coord_kept]; if ( ( ( (yi<=y) && (y(side,candidate,side_point,distance); + Point3f side_point; + float distance; + vcg::SegmentPointDistance(side,candidate,side_point,distance); if( distance < nearest_distance ){ nearest_point=side_point; nearest_distance=distance; - } + } } initial_status=nearest_point; return initial_status; @@ -696,7 +700,7 @@ void PolarMode::Apply (Trackball * tb, Point3f new_point) endb = beta + angley; if(endb > top) endb = top; if(endb < -top) endb = -top; - tb->track.rot = Quaternionf (endb, Point3f(1,0,0)) * + tb->track.rot = Quaternionf (endb, Point3f(1,0,0)) * Quaternionf (enda, Point3f(0,1,0)) ; } @@ -718,20 +722,20 @@ void PolarMode::Draw(Trackball * tb){ // Navigator WASD implementation -NavigatorWasdMode::NavigatorWasdMode() { +NavigatorWasdMode::NavigatorWasdMode() { _flipH=1; _flipV=1; SetTopSpeedsAndAcc(1,1,4); - step_height = step_length = 0; - Reset(); + step_height = step_length = 0; + Reset(); }; void NavigatorWasdMode::Reset() { alpha=0; - beta=0; - current_speed.SetZero(); - step_x=0.0f; + beta=0; + current_speed.SetZero(); + step_x=0.0f; - step_current = step_last = 0.0; + step_current = step_last = 0.0; } void NavigatorWasdMode::FlipH(){ @@ -744,56 +748,56 @@ void NavigatorWasdMode::FlipV(){ void NavigatorWasdMode::SetAction() { - + } bool NavigatorWasdMode::IsAnimating(const Trackball * tb){ - const unsigned int MOVEMENT_KEY_MASK = (const unsigned int)(~Trackball::MODIFIER_MASK); - if (tb->current_button & MOVEMENT_KEY_MASK) return true; - if (current_speed!=Point3f(0,0,0)) return true; - if (step_current>0.0) return true; - return false; + const unsigned int MOVEMENT_KEY_MASK = (const unsigned int)(~Trackball::MODIFIER_MASK); + if (tb->current_button & MOVEMENT_KEY_MASK) return true; + if (current_speed!=Point3f(0,0,0)) return true; + if (step_current>0.0) return true; + return false; } void NavigatorWasdMode::Animate(unsigned int msec, Trackball * tb){ - vcg::Point3f acc(0,0,0); - - float sa = sin(-alpha); - float ca = cos(-alpha); - if (tb->current_button & Trackball::KEY_UP ) acc += vcg::Point3f( sa,0,ca)*(accY*_flipH); - if (tb->current_button & Trackball::KEY_DOWN ) acc -= vcg::Point3f( sa,0,ca)*(accY*_flipH); - if (tb->current_button & Trackball::KEY_LEFT ) acc -= vcg::Point3f(-ca,0,sa)*accX; - if (tb->current_button & Trackball::KEY_RIGHT ) acc += vcg::Point3f(-ca,0,sa)*accX; - if (tb->current_button & Trackball::KEY_PGUP ) acc -= vcg::Point3f( 0,1, 0)*accZ; - if (tb->current_button & Trackball::KEY_PGDOWN) acc += vcg::Point3f( 0,1, 0)*accZ; - - float sec = msec/1.0f; - current_speed += acc*sec; - tb->track.tra+=current_speed*sec; - - // compute step height. - Point3f current_speed_h = current_speed; - current_speed_h[1]=0; - float vel = current_speed_h.Norm(); - if (velcurrent_button & Trackball::KEY_UP ) acc += vcg::Point3f( sa,0,ca)*(accY*_flipH); + if (tb->current_button & Trackball::KEY_DOWN ) acc -= vcg::Point3f( sa,0,ca)*(accY*_flipH); + if (tb->current_button & Trackball::KEY_LEFT ) acc -= vcg::Point3f(-ca,0,sa)*accX; + if (tb->current_button & Trackball::KEY_RIGHT ) acc += vcg::Point3f(-ca,0,sa)*accX; + if (tb->current_button & Trackball::KEY_PGUP ) acc -= vcg::Point3f( 0,1, 0)*accZ; + if (tb->current_button & Trackball::KEY_PGDOWN) acc += vcg::Point3f( 0,1, 0)*accZ; + + float sec = msec/1.0f; + current_speed += acc*sec; + tb->track.tra+=current_speed*sec; + + // compute step height. + Point3f current_speed_h = current_speed; + current_speed_h[1]=0; + float vel = current_speed_h.Norm(); + if (veltrack.tra[1]+=step_last; tb->track.tra[1]-=step_current; - step_last=step_current; - + step_last=step_current; + //tb->track.tra[1]+=0.01; } @@ -801,7 +805,7 @@ void NavigatorWasdMode::Apply (Trackball * tb, Point3f new_point) { Point3f hitOld = tb->last_point; Point3f hitNew = new_point; - tb->last_point=new_point; + tb->last_point=new_point; float dx = (hitNew.X() - hitOld.X()); float dy = (hitNew.Y() - hitOld.Y()); @@ -816,15 +820,15 @@ void NavigatorWasdMode::Apply (Trackball * tb, Point3f new_point) if(beta < -top) beta = -top; Point3f viewpoint = tb->track.InverseMatrix()*Point3f(0,0,0); - tb->track.tra = tb->track.rot.Inverse().Rotate(tb->track.tra + viewpoint ) ; - tb->track.rot = Quaternionf (beta , Point3f(1,0,0)) * + tb->track.tra = tb->track.rot.Inverse().Rotate(tb->track.tra + viewpoint ) ; + tb->track.rot = Quaternionf (beta , Point3f(1,0,0)) * Quaternionf (alpha, Point3f(0,1,0)) ; - tb->track.tra = tb->track.rot.Rotate(tb->track.tra) - viewpoint ; + tb->track.tra = tb->track.rot.Rotate(tb->track.tra) - viewpoint ; - tb->track.tra[1]+=step_last; + tb->track.tra[1]+=step_last; tb->track.tra[1]-=step_current; - - step_last=step_current; + + step_last=step_current; } @@ -833,7 +837,7 @@ void NavigatorWasdMode::SetTopSpeedsAndAcc(float hspeed, float vspeed, float acc hspeed /= 1000; vspeed /= 1000; acc /= 1000000; - + accX = accY = acc; dumping = hspeed / ( hspeed + acc ); accZ = ( vspeed / dumping ) - vspeed; @@ -843,11 +847,11 @@ void NavigatorWasdMode::SetTopSpeedsAndAcc(float hspeed, float vspeed, float acc dumping=0.0; } topSpeedH = hspeed; topSpeedV=vspeed; - + } void NavigatorWasdMode::SetStepOnWalk(float width, float height){ - step_length = width; + step_length = width; step_height = height; } @@ -858,5 +862,5 @@ void NavigatorWasdMode::Apply (Trackball * tb, float WheelNotch) bool NavigatorWasdMode::isSticky(){ - return false; + return false; } diff --git a/wrap/gui/trackutils.h b/wrap/gui/trackutils.h index ef1da994..28d981a8 100644 --- a/wrap/gui/trackutils.h +++ b/wrap/gui/trackutils.h @@ -20,51 +20,7 @@ * for more details. * * * ****************************************************************************/ -/**************************************************************************** - History -$Log: not supported by cvs2svn $ -Revision 1.13 2008/02/26 18:46:55 ponchio -Fixed bug in drawing position of the trackball when changin center. - -Revision 1.12 2008/02/24 18:10:54 ponchio -Fixed scale behaviour. - -Revision 1.11 2008/02/24 18:05:08 ponchio -Should work as before. I didn't test cylinder and other exotic modes. - -Revision 1.10 2008/02/24 14:37:00 ponchio -Restored trackball functionality. Not very much tested, and code will need some -cleanup. - -Revision 1.9 2008/02/22 18:57:47 benedetti -first attempt to correct after quaternion ToMatrix() inversion (does not work yet) - -Revision 1.8 2008/02/15 20:54:45 benedetti -removed some variable initialization related warning - -Revision 1.7 2007/10/22 14:39:54 cignoni -corrected bug into the drawsphere (thanks to nico and guido!) - -Revision 1.6 2007/08/17 09:19:40 cignoni -glEnable (GL_LINE_SMOOTH) should go before changing the linewidth. - -Revision 1.5 2007/07/14 12:44:40 benedetti -Minor edits in Doxygen documentation. - -Revision 1.4 2007/07/09 22:41:22 benedetti -Added Doxygen documentation, removed using namespace std, some other minor changes. - -Revision 1.3 2007/06/12 08:58:08 benedetti -Minor fix in DrawUglyCylinderMode() - -Revision 1.2 2007/05/28 08:10:47 fiorin -Removed type cast warnings - -Revision 1.1 2007/05/15 14:57:34 benedetti -Utility functions for the trackmodes, first version - -****************************************************************************/ #ifndef TRACKUTILS_H #define TRACKUTILS_H @@ -144,24 +100,24 @@ Point3f HitViewPlane (Trackball * tb, const Point3f & p)
The original documentation (in italian) follows:
-dato un punto in coordinate di schermo e.g. in pixel stile opengl 
-calcola il punto di intersezione tra la viewline  che passa per 
+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 
+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 
+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 
+y = - ----------- * x + hitplane.y
       viewpoint.x
 
-eq hiperboloide di raggio r (e.g. che passa per (r/sqrt2,r/sqrt2) 
+eq hiperboloide di raggio r (e.g. che passa per (r/sqrt2,r/sqrt2)
 
      1
 y = --- * (r^2 /2.0)
-     x 
+     x
 
  hitplane.y
  ----------- * x^2 - hitplane.y *x + (r^2/2.0) == 0
@@ -214,16 +170,16 @@ bool HitHyper (Point3f center, float radius, Point3f viewpoint, Plane3f vp,
 
   
The original documentation (in italian) follows:
-dato un punto in coordinate di schermo e.g. in pixel stile opengl 
-restituisce un punto in coordinate di mondo sulla superficie 
+dato un punto in coordinate di schermo e.g. in pixel stile opengl
+restituisce un punto in coordinate di mondo sulla superficie
 della trackball.
-La superficie della trackball e' data da una sfera + una porzione 
+La superficie della trackball e' data da una sfera + una porzione
 di iperboloide di rotazione.
-Assumiamo la sfera di raggio unitario e centrata sull'origine e 
+Assumiamo la sfera di raggio unitario e centrata sull'origine e
 di guardare lungo la y negativa.
 
-                                    X   0   sqrt(1/2)  1  
-eq sfera:              y=sqrt(1-x*x);   1   sqrt(1/2)  0   
+                                    X   0   sqrt(1/2)  1
+eq sfera:              y=sqrt(1-x*x);   1   sqrt(1/2)  0
 eq iperboloide :       y=1/2*x;         inf  sqrt(1/2)  1/2
 eq cono                y=x+sqrt(2);
 
@@ -235,12 +191,12 @@ eq cono y=x+sqrt(2); Point3f HitSphere (Trackball * tb, const Point3f & p) { Point3f center = tb->center; - Line3fN ln = tb->camera.ViewLineFromWindow (Point3f (p[0], p[1], 0)); + Line3fN ln = tb->camera.ViewLineFromWindow (Point3f (p[0], p[1], 0)); Plane3f vp = GetViewPlane (tb->camera, center); Point3f hitPlane(0,0,0), //intersection view plane with point touched - hitSphere(0,0,0), - hitSphere1(0,0,0), - hitSphere2(0,0,0), + hitSphere(0,0,0), + hitSphere1(0,0,0), + hitSphere2(0,0,0), hitHyper(0,0,0); IntersectionPlaneLine < float >(vp, ln, hitPlane); @@ -297,7 +253,7 @@ Point3f HitSphere (Trackball * tb, const Point3f & p) // if(d > d2) hit = hit2; // hit -= tb->center; //} else { - // if(d > 2.99 * Thr) + // if(d > 2.99 * Thr) // d = 2.99 * Thr; // Point3f norm = (hit - tb->center)^(viewpoint - tb->center); // norm.Normalize(); @@ -337,7 +293,7 @@ std::pair< float, bool > LineLineDistance(const Line3f & P,const Line3f & Q,Poin const float det = ( VPVP * VQVQ ) - ( VPVQ * VPVQ ); const float EPSILON = 0.00001f; if ( fabs(det) < EPSILON ) { - return std::make_pair(Distance(P,q0), true); + return std::make_pair(Distance(P,q0), true); } float b1= (q0 - p0).dot(Vp); float b2= (p0 - q0).dot(Vq); @@ -351,7 +307,7 @@ std::pair< float, bool > LineLineDistance(const Line3f & P,const Line3f & Q,Poin /*! @brief Calculates the minimal distance between a ray and a line. - R is the ray and Q is the line, R_s and Q_t are set to be the closest points on + R is the ray and Q is the line, R_s and Q_t are set to be the closest points on the ray and the line. it's returned the distance from R_s and Q_t, and a boolean value which is true @@ -373,7 +329,7 @@ std::pair< float, bool > RayLineDistance(const Ray3f & R,const Line3f & Q,Point3 const float det = ( VRVR * VQVQ ) - ( VRVQ * VRVQ ); const float EPSILON = 0.00001f; if ( ( det >= 0.0f ? det : -det) < EPSILON ) { - return std::make_pair(Distance(Q,r0), true); + return std::make_pair(Distance(Q,r0), true); } float b1= (q0 - r0).dot(Vr); float b2= (r0 - q0).dot(Vq); @@ -381,7 +337,7 @@ std::pair< float, bool > RayLineDistance(const Ray3f & R,const Line3f & Q,Point3 float t = ( (VRVQ * b1) + (VRVR * b2) ) / det; if(s<0){ R_s = r0; - Q_t = ClosestPoint(Q,R_s); + Q_t = ClosestPoint(Q,R_s); }else { R_s = r0 + (Vr * s); Q_t = q0 + (Vq * t); @@ -392,7 +348,7 @@ std::pair< float, bool > RayLineDistance(const Ray3f & R,const Line3f & Q,Point3 ///*! // @brief Calculates the minimal distance between 2 segments. // -// R e Q are the segments, R_s and Q_t are set to be the closest points on +// R e Q are the segments, R_s and Q_t are set to be the closest points on // the segments. // // it's returned the distance from R_s and Q_t, and a boolean value which is true @@ -407,7 +363,7 @@ std::pair< float, bool > RayLineDistance(const Ray3f & R,const Line3f & Q,Point3 //{ // float R_len=Distance(R.P0(),R.P1()); // float Q_len=Distance(Q.P0(),Q.P1()); -// const float EPSILON_LENGTH = std::max(R_len,Q_len)*0.0001f; +// const float EPSILON_LENGTH = std::max(R_len,Q_len)*0.0001f; // if(R_len < EPSILON_LENGTH){ // R_s=R.P0(); // Q_t=ClosestPoint(Q,R_s); @@ -417,7 +373,7 @@ std::pair< float, bool > RayLineDistance(const Ray3f & R,const Line3f & Q,Point3 // Q_t=Q.P0(); // R_s=ClosestPoint(R,Q_t); // return std::make_pair(Distance(R_s,Q_t),true); -// } +// } // Point3f r0 = R.P0(), Vr = (R.P1()-R.P0()).normalized(); // Point3f q0 = Q.P0(), Vq = (Q.P1()-Q.P0()).normalized(); // float VRVR = Vr.dot(Vr); @@ -450,7 +406,7 @@ std::pair< float, bool > RayLineDistance(const Ray3f & R,const Line3f & Q,Point3 // assert(0); // } // } -// } +// } // return std::make_pair(Distance(R_s,Q_t),true); // } // float b1= (q0 - r0).dot(Vr); @@ -465,7 +421,7 @@ std::pair< float, bool > RayLineDistance(const Ray3f & R,const Line3f & Q,Point3 // R_s = r0 + (Vr * s); // } // if( t < 0){ -// Q_t = Q.P0(); +// Q_t = Q.P0(); // }else if ( t > Q_len ){ // Q_t = Q.P1(); // }else{ @@ -477,7 +433,7 @@ std::pair< float, bool > RayLineDistance(const Ray3f & R,const Line3f & Q,Point3 /*! @brief Compute the point on a line closest to the ray projection of a window coordinate point. - Given a window coordinate point, computes a ray starting from the manipulator + Given a window coordinate point, computes a ray starting from the manipulator camera eye and passing through the point's projection on the viewplane, then uses RayLineDistance() to get the closest point to ray on a given line. @see RayLineDistance(const Ray3f & R,const Line3f & Q,Point3f & R_s, Point3f & Q_t) @@ -489,10 +445,10 @@ std::pair< float, bool > RayLineDistance(const Ray3f & R,const Line3f & Q,Point3 std::pair< Point3f,bool > HitNearestPointOnAxis (Trackball * tb,Line3f axis, Point3f point) { Ray3fN ray = line2ray(tb->camera.ViewLineFromWindow (point)); - Point3f axis_p(0,0,0), ray_p(0,0,0); + Point3f axis_p(0,0,0), ray_p(0,0,0); std::pair< float, bool > resp=RayLineDistance(ray,axis,ray_p,axis_p); if(resp.second || (ray_p == ray.Origin())){ - return std::make_pair(Point3f(0,0,0),false); + return std::make_pair(Point3f(0,0,0),false); } return std::make_pair(axis_p,true); } @@ -570,7 +526,7 @@ template /*! @brief Project a window coordinate point on a plane. - Given a window coordinate point, computes a ray starting from the manipulator + Given a window coordinate point, computes a ray starting from the manipulator camera eye and passing through the point's projection on the viewplane, then uses IntersectionRayPlane() to get the ray intersection with a given plane. @@ -684,7 +640,7 @@ void DrawCircle (bool planehandle=true) @param active boolean to be set to true if the icon is active. */ void DrawSphereIcon (Trackball * tb, bool active, bool planeshandle=false) -{ +{ glPushAttrib(GL_TRANSFORM_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | GL_LINE_BIT | GL_CURRENT_BIT | GL_LIGHTING_BIT); glMatrixMode(GL_MODELVIEW); glPushMatrix (); @@ -693,7 +649,7 @@ void DrawSphereIcon (Trackball * tb, bool active, bool planeshandle=false) Point3f center = tb->center + tb->track.InverseMatrix()*Point3f(0, 0, 0); glTranslate(center); glScale (tb->radius/tb->track.sca); - + float amb[4] = { .35f, .35f, .35f, 1.0f }; float col[4] = { .5f, .5f, .8f, 1.0f }; glEnable (GL_LINE_SMOOTH); @@ -709,10 +665,10 @@ void DrawSphereIcon (Trackball * tb, bool active, bool planeshandle=false) glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor (DH.color); glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, amb); - + col[0] = .40f; col[1] = .40f; col[2] = .85f; glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, col); - DrawCircle(planeshandle); + DrawCircle(planeshandle); glRotatef (90, 1, 0, 0); col[0] = .40f; col[1] = .85f; col[2] = .40f; @@ -722,10 +678,10 @@ void DrawSphereIcon (Trackball * tb, bool active, bool planeshandle=false) glRotatef (90, 0, 1, 0); col[0] = .85f; col[1] = .40f; col[2] = .40f; glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, col); - DrawCircle(planeshandle); - - glPopMatrix (); - glPopAttrib (); + DrawCircle(planeshandle); + + glPopMatrix (); + glPopAttrib (); } // TEMPORARY drawing section @@ -762,7 +718,7 @@ void prepare_attrib() void DrawUglyLetter(Trackball * tb,std::vector ugly_letter) { Point3f center=tb->camera.Project(tb->center); - float offset=0; + float offset=0; offset=(std::max)(offset,Distance(center,tb->camera.Project(tb->center+(Point3f(1,0,0) * tb->radius)))); offset=(std::max)(offset,Distance(center,tb->camera.Project(tb->center+(Point3f(0,1,0) * tb->radius)))); offset=(std::max)(offset,Distance(center,tb->camera.Project(tb->center+(Point3f(0,0,1) * tb->radius)))); @@ -775,12 +731,12 @@ void DrawUglyLetter(Trackball * tb,std::vector ugly_letter) prepare_attrib(); glColor3f(1,1,1); glLineWidth(4.0); - + glBegin(GL_LINE_STRIP); for(unsigned int i=0;icamera.UnProject(center+(ugly_letter[i] * offset * 0.25) - +Point3f(-offset,-offset,0))); - } + glVertex(tb->camera.UnProject(center+(ugly_letter[i] * offset * 0.25) + +Point3f(-offset,-offset,0))); + } glEnd(); glPopAttrib (); glPopMatrix(); @@ -800,9 +756,9 @@ void DrawUglyPanMode(Trackball * tb) ugly_p.push_back(Point3f(-1,-1,0)); ugly_p.push_back(Point3f(-1,1,0)); ugly_p.push_back(Point3f(1,1,0)); - ugly_p.push_back(Point3f(1,0,0)); - ugly_p.push_back(Point3f(-1,0,0)); - + ugly_p.push_back(Point3f(1,0,0)); + ugly_p.push_back(Point3f(-1,0,0)); + DrawUglyLetter(tb,ugly_p); } @@ -915,7 +871,7 @@ void DrawUglyPlaneMode(Trackball * tb,Plane3f plane) glVertex(p0+(d1*f0)+(d2*f1)); } glEnd(); - } + } glColor3f(0.9f, 0.9f, 0.2f); glPointSize(8.0f); glBegin(GL_POINTS); @@ -968,7 +924,7 @@ void DrawUglyCylinderMode(Trackball * tb,Line3f axis) glVertex(axis.Origin()+p0+(norm*float(i))+(d1*f0)+(d2*f1)); } glEnd(); - } + } glLineWidth(3.0); glColor3f(0.2f, 0.2f, 0.9f); glBegin(GL_LINES); @@ -1126,15 +1082,15 @@ void DrawUglyAreaMode(Trackball * tb,const std::vector < Point3f > &points, glVertex(p0+(d1*f0)+(d2*f1)); } glEnd(); - } - + } + glPopAttrib (); glPopMatrix(); } } //end namespace trackutils - + } //end namespace vcg #endif //TRACKUTILS_H diff --git a/wrap/gui/view.h b/wrap/gui/view.h index 4b2cca77..b6b2ebcf 100644 --- a/wrap/gui/view.h +++ b/wrap/gui/view.h @@ -108,6 +108,7 @@ Note: mainly it is used only by the TrackBall. template class View { public: + View(); void GetView(); void SetView(const float *_proj, const float *_modelview, const int *_viewport); Point3 Project(const Point3 &p) const; @@ -134,15 +135,23 @@ public: Matrix44 matrix; Matrix44 inverse; int viewport[4]; + bool isOrtho; }; -template void View::GetView() { - glGetv(GL_PROJECTION_MATRIX,proj); - glGetv(GL_MODELVIEW_MATRIX,model); - glGetIntegerv(GL_VIEWPORT, (GLint*)viewport); +template View::View() { + isOrtho=false; +} - matrix = proj*model; - inverse = vcg::Inverse(matrix); +template void View::GetView() { + glGetv(GL_PROJECTION_MATRIX,proj); + glGetv(GL_MODELVIEW_MATRIX,model); + glGetIntegerv(GL_VIEWPORT, (GLint*)viewport); + + if(proj[3][3]==0) isOrtho = false; + else isOrtho = true; + + matrix = proj*model; + inverse = vcg::Inverse(matrix); } template void View::SetView(const float *_proj, @@ -161,6 +170,7 @@ template void View::SetView(const float *_proj, } template Point3 View::ViewPoint() const { + if(isOrtho) return vcg::Inverse(model)* Point3(0, 0, 3); return vcg::Inverse(model)* Point3(0, 0, 0); } // Note that p it is assumed to be in model coordinate. @@ -179,22 +189,33 @@ template Plane3 View::ViewPlaneFromModel(const Point3 &p) // Note that p it is assumed to be in model coordinate. template Line3 View::ViewLineFromModel(const Point3 &p) { - Point3 vp=ViewPoint(); Line3 line; - line.SetOrigin(vp); - line.SetDirection(p - vp); + Point3 vp=ViewPoint(); + if(isOrtho){ + line.SetOrigin(p); + line.SetDirection(- vp ); + } else { + line.SetOrigin(vp); + line.SetDirection(p - vp); + } return line; } // Note that p it is assumed to be in window coordinate. template Line3 View::ViewLineFromWindow(const Point3 &p) { - Line3 ln; // plane perpedicular to view direction and passing through manip center - Point3 vp=ViewPoint(); - Point3 pp=UnProject(p); - ln.SetOrigin(vp); - ln.SetDirection(pp-vp); - return ln; + Line3 line; // plane perpedicular to view direction and passing through manip center + Point3 vp=ViewPoint(); + Point3 pp=UnProject(p); + + if(isOrtho){ + line.SetOrigin(pp); + line.SetDirection(- vp ); + } else { + line.SetOrigin(vp); + line.SetDirection(pp-vp); + } + return line; } template Point3 View::Project(const Point3 &p) const {