Trackball Improvement. Now it works well also for ortho views

This commit is contained in:
Paolo Cignoni 2014-11-04 23:16:04 +00:00
parent 63046a8bab
commit 1ff3a301ec
3 changed files with 266 additions and 285 deletions

View File

@ -42,7 +42,7 @@ void TrackMode::SetAction (){}
void TrackMode::Reset (){} void TrackMode::Reset (){}
bool TrackMode::IsAnimating(const Trackball *){ bool TrackMode::IsAnimating(const Trackball *){
return false; return false;
} }
void TrackMode::Animate(unsigned int, Trackball *){ void TrackMode::Animate(unsigned int, Trackball *){
@ -72,9 +72,13 @@ void SphereMode::Apply (Trackball * tb, Point3f new_point)
tb->Hits.push_back (hitNew); tb->Hits.push_back (hitNew);
Point3f center = tb->center; Point3f center = tb->center;
Point3f axis = (hitNew - center) ^ (hitOld - center); Point3f axis = (hitNew - center) ^ (hitOld - center);
vcg::Normalize(axis);
// Figure out how much to rotate around that axis. // Figure out how much to rotate around that axis.
float phi = Distance (hitNew, hitOld) / tb->radius; // float phi = Distance (hitNew, hitOld) / tb->radius;
// tb->track.rot = tb->last_track.rot * Quaternionf (-phi, axis); // 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; tb->track.rot = Quaternionf (-phi, axis) * tb->last_track.rot;
} }
@ -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 > hitOld = HitPlane(tb,tb->last_point,plane);
std::pair< Point3f, bool > hitNew = HitPlane(tb,new_point,plane); std::pair< Point3f, bool > hitNew = HitPlane(tb,new_point,plane);
if(hitOld.second && hitNew.second){ if(hitOld.second && hitNew.second){
tb->Translate (hitNew.first - hitOld.first); tb->Translate (hitNew.first - hitOld.first);
} }
} }
@ -242,21 +246,21 @@ Point3f PathMode::SetStartNear(Point3f point)
float nearest_distance=Distance(nearest_point,point); float nearest_distance=Distance(nearest_point,point);
unsigned int npts = int(points.size()); unsigned int npts = int(points.size());
for(unsigned int i = 1;i <= npts;i++){ for(unsigned int i = 1;i <= npts;i++){
if( i == npts){ if( i == npts){
if (wrap){ if (wrap){
p0=points[npts-1]; p0=points[npts-1];
p1=points[0]; p1=points[0];
} else { } else {
break; break;
} }
} else { } else {
p0=points[i-1]; p0=points[i-1];
p1=points[i]; p1=points[i];
} }
//Point3f segment_point=ClosestPoint(Segment3f(p0,p1),point); //Point3f segment_point=ClosestPoint(Segment3f(p0,p1),point);
Point3f segment_point; Point3f segment_point;
float distance; float distance;
vcg::SegmentPointDistance<float>(Segment3f(p0,p1),point,segment_point,distance); vcg::SegmentPointDistance<float>(Segment3f(p0,p1),point,segment_point,distance);
// float distance=Distance(segment_point,point); // float distance=Distance(segment_point,point);
if(distance<nearest_distance){ if(distance<nearest_distance){
nearest_point=segment_point; nearest_point=segment_point;
@ -283,17 +287,17 @@ void PathMode::GetPoints(float state, Point3f & point, Point3f & prev_point, Poi
Point3f p0(0,0,0),p1(0,0,0); Point3f p0(0,0,0),p1(0,0,0);
unsigned int npts = int(points.size()); unsigned int npts = int(points.size());
for(unsigned int i = 1;i <= npts;i++){ for(unsigned int i = 1;i <= npts;i++){
if( i == npts){ if( i == npts){
if (wrap){ if (wrap){
p0=points[npts-1]; p0=points[npts-1];
p1=points[0]; p1=points[0];
} else { } else {
break; break;
} }
} else { } else {
p0=points[i-1]; p0=points[i-1];
p1=points[i]; p1=points[i];
} }
float segment_norm= Distance(p0,p1) / path_length; float segment_norm= Distance(p0,p1) / path_length;
if (segment_norm < remaining_norm){ if (segment_norm < remaining_norm){
remaining_norm -= segment_norm; remaining_norm -= segment_norm;
@ -303,24 +307,24 @@ void PathMode::GetPoints(float state, Point3f & point, Point3f & prev_point, Poi
next_point = p1; next_point = p1;
float ratio= remaining_norm / segment_norm; float ratio= remaining_norm / segment_norm;
point = prev_point + (( next_point - prev_point ) * ratio); 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){ if(Distance(point,prev_point) < EPSILON){
point=prev_point; point=prev_point;
if (i > 1){ if (i > 1){
prev_point=points[i-2]; prev_point=points[i-2];
} else if (wrap){ } else if (wrap){
prev_point=points[npts-1]; prev_point=points[npts-1];
} }
} else if (Distance(point,next_point) < EPSILON){ } else if (Distance(point,next_point) < EPSILON){
point=next_point; point=next_point;
if( i < (npts-1)){ if( i < (npts-1)){
next_point=points[i+1]; next_point=points[i+1];
} else { } else {
if (wrap){ if (wrap){
next_point=points[1]; next_point=points[1];
} else { } else {
next_point=points[npts-1]; next_point=points[npts-1];
} }
} }
} }
return; return;
@ -412,14 +416,14 @@ float PathMode::HitPoint(float state, Ray3fN ray, Point3f &hit_point)
Segment3f active_segment; Segment3f active_segment;
if (verse > 0){ if (verse > 0){
active_segment=Segment3f(current_point,next_point); active_segment=Segment3f(current_point,next_point);
} else { } else {
active_segment= Segment3f(current_point,prev_point); active_segment= Segment3f(current_point,prev_point);
} }
//hit_point=ClosestPoint(active_segment,closest_point); //hit_point=ClosestPoint(active_segment,closest_point);
float dist; float dist;
vcg::SegmentPointDistance<float>(active_segment,closest_point,hit_point,dist); vcg::SegmentPointDistance<float>(active_segment,closest_point,hit_point,dist);
return verse * ((hit_point-current_point).Norm() / path_length); return verse * ((hit_point-current_point).Norm() / path_length);
} }
@ -471,14 +475,14 @@ void AreaMode::Init(const std::vector < Point3f > &pts)
bool pts_not_in_line=false; bool pts_not_in_line=false;
Point3f a,b; Point3f a,b;
for(unsigned int i=0;i<onethird;i++){ for(unsigned int i=0;i<onethird;i++){
a=(pts[(i+ onethird )%npts] - pts[i%npts]).normalized(); a=(pts[(i+ onethird )%npts] - pts[i%npts]).normalized();
b=(pts[(i+(2*onethird))%npts] - pts[i%npts]).normalized(); b=(pts[(i+(2*onethird))%npts] - pts[i%npts]).normalized();
pts_not_in_line = (a ^ b).Norm() > EPSILON; pts_not_in_line = (a ^ b).Norm() > EPSILON;
if(pts_not_in_line){ if(pts_not_in_line){
plane.Init( pts[i%npts], plane.Init( pts[i%npts],
pts[(i+(onethird))%npts], pts[(i+(onethird))%npts],
pts[(i+(2*onethird))%npts]); pts[(i+(2*onethird))%npts]);
break; break;
} }
} }
assert(pts_not_in_line); assert(pts_not_in_line);
@ -498,11 +502,11 @@ void AreaMode::Init(const std::vector < Point3f > &pts)
} }
points.reserve(npts); points.reserve(npts);
for(unsigned int i=0;i<npts;i++){ for(unsigned int i=0;i<npts;i++){
points.push_back(plane.Projection(pts[i])); points.push_back(plane.Projection(pts[i]));
} }
min_side_length=Distance(points[0],points[1]); min_side_length=Distance(points[0],points[1]);
for(unsigned int i=1;i<npts;i++){ for(unsigned int i=1;i<npts;i++){
min_side_length=(std::min)(Distance(points[i-1],points[i]),min_side_length); min_side_length=(std::min)(Distance(points[i-1],points[i]),min_side_length);
} }
rubberband_handle=old_status=status=initial_status=p0; rubberband_handle=old_status=status=initial_status=p0;
} }
@ -528,7 +532,7 @@ void AreaMode::Apply (Trackball * tb, Point3f new_point)
} }
std::pair< Point3f, bool > hitNew = HitPlane(tb,new_point+delta_mouse,plane); std::pair< Point3f, bool > hitNew = HitPlane(tb,new_point+delta_mouse,plane);
if(! hitNew.second){ if(! hitNew.second){
return; return;
} }
Point3f hit_point=hitNew.first; Point3f hit_point=hitNew.first;
Point3f delta_status=Move(status,hit_point); Point3f delta_status=Move(status,hit_point);
@ -555,7 +559,7 @@ Point3f AreaMode::Move(Point3f start,Point3f end)
bool done=false; bool done=false;
bool end_inside=Inside(end); bool end_inside=Inside(end);
while(!done){ while(!done){
path.push_back(pt); path.push_back(pt);
Segment3f segment(pt,end); Segment3f segment(pt,end);
bool p_on_side = false; bool p_on_side = false;
bool hit=false; bool hit=false;
@ -568,25 +572,25 @@ Point3f AreaMode::Move(Point3f start,Point3f end)
Segment3f side(points[i],points[j]); Segment3f side(points[i],points[j]);
Point3f pseg,psid; Point3f pseg,psid;
//std::pair<float,bool> res=SegmentSegmentDistance(segment,side,pseg,psid); //std::pair<float,bool> res=SegmentSegmentDistance(segment,side,pseg,psid);
std::pair<float,bool> res; std::pair<float,bool> res;
vcg::SegmentSegmentDistance(segment,side,res.first,res.second,pseg,psid); vcg::SegmentSegmentDistance(segment,side,res.first,res.second,pseg,psid);
if(res.first < EPSILON && ! res.second){ if(res.first < EPSILON && ! res.second){
float dist= Distance(pt,pseg); float dist= Distance(pt,pseg);
if(dist < EPSILON){ if(dist < EPSILON){
//Point3f pn=ClosestPoint(side,end); //Point3f pn=ClosestPoint(side,end);
Point3f pn; Point3f pn;
float dist; float dist;
vcg::SegmentPointDistance<float>(side,end,pn,dist); vcg::SegmentPointDistance<float>(side,end,pn,dist);
if(!p_on_side || (Distance(pn,end)<Distance(end,pside))){ if(!p_on_side || (Distance(pn,end)<Distance(end,pside))){
pside=pn; pside=pn;
p_on_side=true; p_on_side=true;
} }
} else { } else {
if (!hit || Distance(pt,pseg) < Distance(pt,phit)){ if (!hit || Distance(pt,pseg) < Distance(pt,phit)){
phit=pseg; phit=pseg;
hit=true; hit=true;
} }
} }
} }
} }
if (p_on_side) if (p_on_side)
@ -620,15 +624,15 @@ bool AreaMode::Inside(Point3f point)
float yi, yj, xi, xj; float yi, yj, xi, xj;
int i, j, np=int(points.size()); int i, j, np=int(points.size());
for (i = 0, j = np-1; i < np; j = i++) { for (i = 0, j = np-1; i < np; j = i++) {
xi=points[i][first_coord_kept]; xi=points[i][first_coord_kept];
yi=points[i][second_coord_kept]; yi=points[i][second_coord_kept];
xj=points[j][first_coord_kept]; xj=points[j][first_coord_kept];
yj=points[j][second_coord_kept]; yj=points[j][second_coord_kept];
if ( ( ( (yi<=y) && (y<yj) ) || ( (yj<=y) && (y<yi) ) ) && if ( ( ( (yi<=y) && (y<yj) ) || ( (yj<=y) && (y<yi) ) ) &&
( x < ( xj - xi ) * ( y - yi ) / ( yj - yi ) + xi ) ) ( x < ( xj - xi ) * ( y - yi ) / ( yj - yi ) + xi ) )
{ {
inside=!inside; inside=!inside;
} }
} }
return inside; return inside;
} }
@ -647,9 +651,9 @@ Point3f AreaMode::SetStartNear(Point3f point)
Segment3f side(points[i],points[j]); Segment3f side(points[i],points[j]);
//Point3f side_point=ClosestPoint(side,candidate); //Point3f side_point=ClosestPoint(side,candidate);
//float distance=Distance(side_point,candidate); //float distance=Distance(side_point,candidate);
Point3f side_point; Point3f side_point;
float distance; float distance;
vcg::SegmentPointDistance<float>(side,candidate,side_point,distance); vcg::SegmentPointDistance<float>(side,candidate,side_point,distance);
if( distance < nearest_distance ){ if( distance < nearest_distance ){
nearest_point=side_point; nearest_point=side_point;
nearest_distance=distance; nearest_distance=distance;
@ -721,17 +725,17 @@ void PolarMode::Draw(Trackball * tb){
NavigatorWasdMode::NavigatorWasdMode() { NavigatorWasdMode::NavigatorWasdMode() {
_flipH=1; _flipV=1; _flipH=1; _flipV=1;
SetTopSpeedsAndAcc(1,1,4); SetTopSpeedsAndAcc(1,1,4);
step_height = step_length = 0; step_height = step_length = 0;
Reset(); Reset();
}; };
void NavigatorWasdMode::Reset() { void NavigatorWasdMode::Reset() {
alpha=0; alpha=0;
beta=0; beta=0;
current_speed.SetZero(); current_speed.SetZero();
step_x=0.0f; step_x=0.0f;
step_current = step_last = 0.0; step_current = step_last = 0.0;
} }
void NavigatorWasdMode::FlipH(){ void NavigatorWasdMode::FlipH(){
@ -748,51 +752,51 @@ void NavigatorWasdMode::SetAction() {
} }
bool NavigatorWasdMode::IsAnimating(const Trackball * tb){ bool NavigatorWasdMode::IsAnimating(const Trackball * tb){
const unsigned int MOVEMENT_KEY_MASK = (const unsigned int)(~Trackball::MODIFIER_MASK); const unsigned int MOVEMENT_KEY_MASK = (const unsigned int)(~Trackball::MODIFIER_MASK);
if (tb->current_button & MOVEMENT_KEY_MASK) return true; if (tb->current_button & MOVEMENT_KEY_MASK) return true;
if (current_speed!=Point3f(0,0,0)) return true; if (current_speed!=Point3f(0,0,0)) return true;
if (step_current>0.0) return true; if (step_current>0.0) return true;
return false; return false;
} }
void NavigatorWasdMode::Animate(unsigned int msec, Trackball * tb){ void NavigatorWasdMode::Animate(unsigned int msec, Trackball * tb){
vcg::Point3f acc(0,0,0); vcg::Point3f acc(0,0,0);
float sa = sin(-alpha); float sa = sin(-alpha);
float ca = cos(-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_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_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_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_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_PGUP ) acc -= vcg::Point3f( 0,1, 0)*accZ;
if (tb->current_button & Trackball::KEY_PGDOWN) 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; float sec = msec/1.0f;
current_speed += acc*sec; current_speed += acc*sec;
tb->track.tra+=current_speed*sec; tb->track.tra+=current_speed*sec;
// compute step height. // compute step height.
Point3f current_speed_h = current_speed; Point3f current_speed_h = current_speed;
current_speed_h[1]=0; current_speed_h[1]=0;
float vel = current_speed_h.Norm(); float vel = current_speed_h.Norm();
if (vel<topSpeedH*0.05) { if (vel<topSpeedH*0.05) {
// stopped: decrease step heigth to zero // stopped: decrease step heigth to zero
step_current*=pow(dumping,sec); step_current*=pow(dumping,sec);
if (step_current<step_height*0.06) { step_current=0; step_x=0.0f;} if (step_current<step_height*0.06) { step_current=0; step_x=0.0f;}
} else { } else {
// running: rise step heigth // running: rise step heigth
vel = current_speed.Norm(); vel = current_speed.Norm();
step_x += vel*sec; step_x += vel*sec;
float step_current_min = (float)fabs(sin( step_x*M_PI / step_length ))*step_height; float step_current_min = (float)fabs(sin( step_x*M_PI / step_length ))*step_height;
if (step_current<step_current_min) step_current=step_current_min; if (step_current<step_current_min) step_current=step_current_min;
} }
current_speed*=pow(dumping,sec); current_speed*=pow(dumping,sec);
if (current_speed.Norm()<topSpeedH*0.005) current_speed.SetZero(); // full stop if (current_speed.Norm()<topSpeedH*0.005) current_speed.SetZero(); // full stop
tb->track.tra[1]+=step_last; tb->track.tra[1]+=step_last;
tb->track.tra[1]-=step_current; tb->track.tra[1]-=step_current;
step_last=step_current; step_last=step_current;
//tb->track.tra[1]+=0.01; //tb->track.tra[1]+=0.01;
} }
@ -801,7 +805,7 @@ void NavigatorWasdMode::Apply (Trackball * tb, Point3f new_point)
{ {
Point3f hitOld = tb->last_point; Point3f hitOld = tb->last_point;
Point3f hitNew = new_point; Point3f hitNew = new_point;
tb->last_point=new_point; tb->last_point=new_point;
float dx = (hitNew.X() - hitOld.X()); float dx = (hitNew.X() - hitOld.X());
float dy = (hitNew.Y() - hitOld.Y()); float dy = (hitNew.Y() - hitOld.Y());
@ -816,15 +820,15 @@ void NavigatorWasdMode::Apply (Trackball * tb, Point3f new_point)
if(beta < -top) beta = -top; if(beta < -top) beta = -top;
Point3f viewpoint = tb->track.InverseMatrix()*Point3f(0,0,0); Point3f viewpoint = tb->track.InverseMatrix()*Point3f(0,0,0);
tb->track.tra = tb->track.rot.Inverse().Rotate(tb->track.tra + viewpoint ) ; tb->track.tra = tb->track.rot.Inverse().Rotate(tb->track.tra + viewpoint ) ;
tb->track.rot = Quaternionf (beta , Point3f(1,0,0)) * tb->track.rot = Quaternionf (beta , Point3f(1,0,0)) *
Quaternionf (alpha, Point3f(0,1,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; tb->track.tra[1]-=step_current;
step_last=step_current; step_last=step_current;
} }
@ -858,5 +862,5 @@ void NavigatorWasdMode::Apply (Trackball * tb, float WheelNotch)
bool NavigatorWasdMode::isSticky(){ bool NavigatorWasdMode::isSticky(){
return false; return false;
} }

View File

@ -20,51 +20,7 @@
* for more details. * * 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 #ifndef TRACKUTILS_H
#define TRACKUTILS_H #define TRACKUTILS_H
@ -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 det = ( VPVP * VQVQ ) - ( VPVQ * VPVQ );
const float EPSILON = 0.00001f; const float EPSILON = 0.00001f;
if ( fabs(det) < EPSILON ) { 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 b1= (q0 - p0).dot(Vp);
float b2= (p0 - q0).dot(Vq); float b2= (p0 - q0).dot(Vq);
@ -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 det = ( VRVR * VQVQ ) - ( VRVQ * VRVQ );
const float EPSILON = 0.00001f; const float EPSILON = 0.00001f;
if ( ( det >= 0.0f ? det : -det) < EPSILON ) { 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 b1= (q0 - r0).dot(Vr);
float b2= (r0 - q0).dot(Vq); float b2= (r0 - q0).dot(Vq);
@ -492,7 +448,7 @@ std::pair< Point3f,bool > HitNearestPointOnAxis (Trackball * tb,Line3f axis, Poi
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); std::pair< float, bool > resp=RayLineDistance(ray,axis,ray_p,axis_p);
if(resp.second || (ray_p == ray.Origin())){ 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); return std::make_pair(axis_p,true);
} }
@ -712,7 +668,7 @@ void DrawSphereIcon (Trackball * tb, bool active, bool planeshandle=false)
col[0] = .40f; col[1] = .40f; col[2] = .85f; col[0] = .40f; col[1] = .40f; col[2] = .85f;
glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, col); glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, col);
DrawCircle(planeshandle); DrawCircle(planeshandle);
glRotatef (90, 1, 0, 0); glRotatef (90, 1, 0, 0);
col[0] = .40f; col[1] = .85f; col[2] = .40f; 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); glRotatef (90, 0, 1, 0);
col[0] = .85f; col[1] = .40f; col[2] = .40f; col[0] = .85f; col[1] = .40f; col[2] = .40f;
glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, col); glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, col);
DrawCircle(planeshandle); DrawCircle(planeshandle);
glPopMatrix (); glPopMatrix ();
glPopAttrib (); glPopAttrib ();
} }
// TEMPORARY drawing section // TEMPORARY drawing section
@ -778,8 +734,8 @@ void DrawUglyLetter(Trackball * tb,std::vector<Point3f> ugly_letter)
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
for(unsigned int i=0;i<ugly_letter.size();i++){ for(unsigned int i=0;i<ugly_letter.size();i++){
glVertex(tb->camera.UnProject(center+(ugly_letter[i] * offset * 0.25) glVertex(tb->camera.UnProject(center+(ugly_letter[i] * offset * 0.25)
+Point3f(-offset,-offset,0))); +Point3f(-offset,-offset,0)));
} }
glEnd(); glEnd();
glPopAttrib (); glPopAttrib ();

View File

@ -108,6 +108,7 @@ Note: mainly it is used only by the TrackBall.
template <class T> class View { template <class T> class View {
public: public:
View();
void GetView(); void GetView();
void SetView(const float *_proj, const float *_modelview, const int *_viewport); void SetView(const float *_proj, const float *_modelview, const int *_viewport);
Point3<T> Project(const Point3<T> &p) const; Point3<T> Project(const Point3<T> &p) const;
@ -134,15 +135,23 @@ public:
Matrix44<T> matrix; Matrix44<T> matrix;
Matrix44<T> inverse; Matrix44<T> inverse;
int viewport[4]; int viewport[4];
bool isOrtho;
}; };
template <class T> void View<T>::GetView() { template <class T> View<T>::View() {
glGetv(GL_PROJECTION_MATRIX,proj); isOrtho=false;
glGetv(GL_MODELVIEW_MATRIX,model); }
glGetIntegerv(GL_VIEWPORT, (GLint*)viewport);
matrix = proj*model; template <class T> void View<T>::GetView() {
inverse = vcg::Inverse(matrix); 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 <class T> void View<T>::SetView(const float *_proj, template <class T> void View<T>::SetView(const float *_proj,
@ -161,6 +170,7 @@ template <class T> void View<T>::SetView(const float *_proj,
} }
template <class T> Point3<T> View<T>::ViewPoint() const { template <class T> Point3<T> View<T>::ViewPoint() const {
if(isOrtho) return vcg::Inverse(model)* Point3<T>(0, 0, 3);
return vcg::Inverse(model)* Point3<T>(0, 0, 0); return vcg::Inverse(model)* Point3<T>(0, 0, 0);
} }
// Note that p it is assumed to be in model coordinate. // Note that p it is assumed to be in model coordinate.
@ -179,22 +189,33 @@ template <class T> Plane3<T> View<T>::ViewPlaneFromModel(const Point3<T> &p)
// Note that p it is assumed to be in model coordinate. // Note that p it is assumed to be in model coordinate.
template <class T> Line3<T> View<T>::ViewLineFromModel(const Point3<T> &p) template <class T> Line3<T> View<T>::ViewLineFromModel(const Point3<T> &p)
{ {
Point3<T> vp=ViewPoint();
Line3<T> line; Line3<T> line;
line.SetOrigin(vp); Point3<T> vp=ViewPoint();
line.SetDirection(p - vp); if(isOrtho){
line.SetOrigin(p);
line.SetDirection(- vp );
} else {
line.SetOrigin(vp);
line.SetDirection(p - vp);
}
return line; return line;
} }
// Note that p it is assumed to be in window coordinate. // Note that p it is assumed to be in window coordinate.
template <class T> Line3<T> View<T>::ViewLineFromWindow(const Point3<T> &p) template <class T> Line3<T> View<T>::ViewLineFromWindow(const Point3<T> &p)
{ {
Line3<T> ln; // plane perpedicular to view direction and passing through manip center Line3<T> line; // plane perpedicular to view direction and passing through manip center
Point3<T> vp=ViewPoint(); Point3<T> vp=ViewPoint();
Point3<T> pp=UnProject(p); Point3<T> pp=UnProject(p);
ln.SetOrigin(vp);
ln.SetDirection(pp-vp); if(isOrtho){
return ln; line.SetOrigin(pp);
line.SetDirection(- vp );
} else {
line.SetOrigin(vp);
line.SetDirection(pp-vp);
}
return line;
} }
template <class T> Point3<T> View<T>::Project(const Point3<T> &p) const { template <class T> Point3<T> View<T>::Project(const Point3<T> &p) const {