00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include <GL/glew.h>
00048 #include <wrap/gl/math.h>
00049 #include <wrap/gl/space.h>
00050 #include <wrap/gl/addons.h>
00051 #include <wrap/qt/gl_label.h>
00052
00053 #include "coordinateframe.h"
00054
00055 using namespace vcg;
00056
00057 CoordinateFrame::CoordinateFrame(float s)
00058 :basecolor(Color4b::White),xcolor(Color4b::Red)
00059 ,ycolor(Color4b::Green),zcolor(Color4b::Blue),size(s),linewidth(2.0)
00060 ,font(),drawaxis(true),drawlabels(true),drawvalues(false)
00061 {
00062 font.setFamily("Helvetica");
00063 }
00064
00065 void CoordinateFrame::Render(QGLWidget* glw,QPainter* p)
00066 {
00067 assert( glw!= NULL);
00068 glPushAttrib(GL_ALL_ATTRIB_BITS);
00069 glDisable(GL_LIGHTING);
00070 glDisable(GL_TEXTURE_2D);
00071 glEnable(GL_BLEND);
00072 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00073 glEnable(GL_LINE_SMOOTH);
00074 glEnable(GL_POINT_SMOOTH);
00075 glLineWidth(linewidth);
00076 glPointSize(linewidth*1.5);
00077 glLabel::Mode md;
00078 Point3d o(0,0,0);
00079 Point3d a(size,0,0);
00080 Point3d b(0,size,0);
00081 Point3d c(0,0,size);
00082
00083 double mm[16],mp[16];
00084 GLint vp[4];
00085 glGetDoublev(GL_MODELVIEW_MATRIX,mm);
00086 glGetDoublev(GL_PROJECTION_MATRIX,mp);
00087 glGetIntegerv(GL_VIEWPORT,vp);
00088 float slope_a=calcSlope(-a,a,2*size,10,mm,mp,vp);
00089 float slope_b=calcSlope(-b,b,2*size,10,mm,mp,vp);
00090 float slope_c=calcSlope(-c,c,2*size,10,mm,mp,vp);
00091 float scalefactor = size*0.02f;
00092 if(drawaxis){
00093 glBegin(GL_LINES);
00094 glColor(xcolor);
00095 glVertex(-a); glVertex(a);
00096 glColor(ycolor);
00097 glVertex(-b); glVertex(b);
00098 glColor(zcolor);
00099 glVertex(-c); glVertex(c);
00100 glEnd();
00101 glColor(basecolor);
00102
00103 drawTickedLine(o,a,size,slope_a,linewidth);
00104 drawTickedLine(o,b,size,slope_b,linewidth);
00105 drawTickedLine(o,c,size,slope_c,linewidth);
00106
00107 drawTickedLine(o,-a,size,slope_a,linewidth);
00108 drawTickedLine(o,-b,size,slope_b,linewidth);
00109 drawTickedLine(o,-c,size,slope_c,linewidth);
00110 glPushMatrix();
00111 glTranslate(a);
00112 glScalef(scalefactor,scalefactor,scalefactor);
00113 Add_Ons::Cone(10,linewidth*1.5,linewidth*0.5,true);
00114 glPopMatrix();
00115 glPushMatrix();
00116 glTranslate(b);
00117 glRotatef(90,0,0,1);
00118 glScalef(scalefactor,scalefactor,scalefactor);
00119 Add_Ons::Cone(10,linewidth*1.5,linewidth*0.5,true);
00120 glPopMatrix();
00121 glPushMatrix();
00122 glTranslate(c);
00123 glRotatef(-90,0,1,0);
00124 glScalef(scalefactor,scalefactor,scalefactor);
00125 Add_Ons::Cone(10,linewidth*1.5,linewidth*0.5,true);
00126 glPopMatrix();
00127 }
00128 if(drawlabels){
00129 md.qFont.setBold(true);
00130 md.qFont.setPixelSize(12);
00131 float d=size+scalefactor*linewidth*1.5;
00132 if (p) {
00133 vcg::glLabel::render(p,vcg::Point3f(d,0,0),QString("X"),md);
00134 vcg::glLabel::render(p,vcg::Point3f(0,d,0),QString("Y"),md);
00135 vcg::glLabel::render(p,vcg::Point3f(0,0,d),QString("Z"),md);
00136 }
00137 }
00138 if(drawvalues){
00139 md.qFont.setBold(false);
00140 md.qFont.setPixelSize(8);
00141 md.color=Color4b(Color4b::LightGray);
00142 float i;
00143 glColor(Color4b::LightGray);
00144 for(i=slope_a;i<size;i+=slope_a){
00145 vcg::glLabel::render(p,vcg::Point3f( i,0,0),QString(" %1").arg(i,3,'f',1),md);
00146 vcg::glLabel::render(p,vcg::Point3f(-i,0,0),QString(" %1").arg(i,3,'f',1),md);
00147 }
00148 for(i=slope_b;i<size;i+=slope_b){
00149 vcg::glLabel::render(p,vcg::Point3f(0, i,0),QString(" %1").arg(i,3,'f',1),md);
00150 vcg::glLabel::render(p,vcg::Point3f(0,-i,0),QString(" %1").arg(i,3,'f',1),md);
00151 }
00152 for(i=slope_c;i<size;i+=slope_c){
00153 vcg::glLabel::render(p,vcg::Point3f(0,0, i),QString(" %1").arg(i,3,'f',1),md);
00154 vcg::glLabel::render(p,vcg::Point3f(0,0,-i),QString(" %1").arg(i,3,'f',1),md);
00155 }
00156 }
00157 glGetError();
00158 glPopAttrib();
00159 assert(!glGetError());
00160 }
00161
00162 void CoordinateFrame::drawTickedLine(const Point3d &a,const Point3d &b, float dim,float tickDist,float linewidth)
00163 {
00164 Point3d v(b-a);
00165 v = v /dim;
00166
00167 glBegin(GL_POINTS);
00168 float i;
00169 for(i=tickDist;i<dim;i+=tickDist)
00170 glVertex3f(a[0] + i*v[0],a[1] + i*v[1],a[2] + i*v[2]);
00171 glEnd();
00172
00173 glPushAttrib(GL_POINT_BIT);
00174 glPointSize(linewidth*3);
00175 glBegin(GL_POINTS);
00176 glVertex3f(a[0] + dim*v[0],a[1] + dim*v[1],a[2] + dim*v[2]);
00177 glEnd();
00178
00179 glPopAttrib();
00180 }
00181
00182 float CoordinateFrame::calcSlope(const Point3d &a,const Point3d &b,float dim,int spacing,double *mm,double *mp,GLint *vp)
00183 {
00184 Point3d p1,p2;
00185
00186 gluProject(a[0],a[1],a[2],mm,mp,vp,&p1[0],&p1[1],&p1[2]);
00187 gluProject(b[0],b[1],b[2],mm,mp,vp,&p2[0],&p2[1],&p2[2]);
00188 p1[2]=p2[2]=0;
00189
00190 float tickNum = spacing/Distance(p2,p1);
00191 float slope = dim*tickNum;
00192 float nslope = math::Min(niceRound(slope), 0.5f*niceRound(2.0f*slope), 0.2f*niceRound(5.0f*slope));
00193 nslope = std::max(niceRound(dim*.001f),nslope);
00194 return nslope;
00195 }
00196
00197 float CoordinateFrame::niceRound(float val)
00198 {
00199 return powf(10.f,ceil(log10(val)));
00200 }
00201
00202 MovableCoordinateFrame::MovableCoordinateFrame(float size)
00203 :CoordinateFrame(size),position(0,0,0),rotation(0,Point3f(1,0,0))
00204 {
00205
00206 }
00207
00208 void MovableCoordinateFrame::Render(QGLWidget* gla, QPainter *p)
00209 {
00210 glPushMatrix();
00211
00212 glTranslate(position);
00213 Matrix44f mrot;
00214 rotation.ToMatrix(mrot);
00215
00216 glMultMatrix(Inverse(mrot));
00217
00218 CoordinateFrame::Render(gla,p);
00219
00220 glPopMatrix();
00221 }
00222
00223 void MovableCoordinateFrame::GetTransform(Matrix44f & transform)
00224 {
00225
00226
00227
00228 transform.SetIdentity();
00229
00230
00231 Matrix44f rot;
00232 rotation.ToMatrix(rot);
00233
00234 transform = Inverse(rot) * transform ;
00235
00236
00237 Matrix44f pos;
00238 pos.SetTranslate(position);
00239
00240 transform = pos * transform;
00241
00242 }
00243
00244 void MovableCoordinateFrame::Reset(bool reset_position,bool reset_alignment)
00245 {
00246 if(reset_position)
00247 position = Point3f(0,0,0);
00248 if(reset_alignment)
00249 rotation = Quaternionf(0,Point3f(1,0,0));
00250 }
00251
00252 void MovableCoordinateFrame::SetPosition(const Point3f newpos)
00253 {
00254 position = newpos;
00255 }
00256
00257 void MovableCoordinateFrame::SetRotation(const Quaternionf newrot)
00258 {
00259 rotation = newrot;
00260 }
00261
00262 Point3f MovableCoordinateFrame::GetPosition()
00263 {
00264 return position;
00265 }
00266
00267 Quaternionf MovableCoordinateFrame::GetRotation()
00268 {
00269 return rotation;
00270 }
00271
00272 void MovableCoordinateFrame::Rot(float angle_deg,const Point3f axis)
00273 {
00274 Similarityf s;
00275 s.SetRotate(math::ToRad(angle_deg),(rotation).Rotate(axis));
00276 Move(s);
00277 }
00278
00279 void MovableCoordinateFrame::AlignWith(const Point3f pri,const Point3f secondary,const char c1, const char c2)
00280 {
00281 const float EPSILON=1e-6f;
00282 Point3f primary=pri;
00283
00284 if( primary.Norm() < EPSILON*size )
00285 return;
00286
00287 primary.Normalize();
00288 Plane3f plane(0,primary);
00289
00290 Point3f x(1,0,0),y(0,1,0),z(0,0,1);
00291 Point3f first(0,0,0),second(0,0,0),third(0,0,0);
00292
00293 if(c1=='X'){ first = x;
00294 if((c2=='Y')||(c2==' ')){ second = y; third = z; }
00295 else if(c2=='Z'){ second = z; third = y; }
00296 else assert (0);
00297 } else if(c1=='Y'){ first = y;
00298 if((c2=='Z')||(c2==' ')){ second = z; third = x; }
00299 else if(c2=='X'){ second = x; third = z; }
00300 else assert (0);
00301 } else if(c1=='Z'){ first = z;
00302 if((c2=='X')||(c2==' ')){ second = x; third = y; }
00303 else if(c2=='Y'){ second = y; third = x; }
00304 else assert (0);
00305 } else assert (0);
00306
00307 Point3f old_first = Inverse(rotation).Rotate(first);
00308 Point3f old_second_pro = plane.Projection(Inverse(rotation).Rotate(second));
00309 Point3f old_third_pro = plane.Projection(Inverse(rotation).Rotate(third));
00310
00311
00312 RotateToAlign(old_first,primary);
00313
00314 Point3f secondary_pro = plane.Projection(secondary);
00315 Point3f new_second_pro = plane.Projection(Inverse(rotation).Rotate(second));
00316
00317 if( secondary.Norm() > EPSILON*size && secondary_pro.Norm() > EPSILON ){
00318
00319 secondary_pro.Normalize();
00320 RotateToAlign(new_second_pro,secondary_pro);
00321 return;
00322 }
00323
00324 if ( old_second_pro.Norm() > EPSILON ) {
00325
00326 old_second_pro.Normalize();
00327 RotateToAlign(new_second_pro,old_second_pro);
00328 return;
00329 }
00330
00331
00332 Point3f new_third_pro = plane.Projection(Inverse(rotation).Rotate(third));
00333 assert(old_third_pro.Norm() > EPSILON );
00334
00335 old_third_pro.Normalize();
00336 RotateToAlign(new_third_pro,old_third_pro);
00337 }
00338
00339 void MovableCoordinateFrame::Move(const Similarityf track)
00340 {
00341 position = position + track.tra;
00342 rotation = rotation * Inverse(track.rot);
00343 }
00344
00345 void MovableCoordinateFrame::RotateToAlign(const Point3f source, const Point3f dest)
00346 {
00347 const float EPSILON=1e-6f;
00348
00349 assert( math::Abs(source.Norm() - 1) < EPSILON);
00350 assert( math::Abs(dest.Norm() - 1) < EPSILON);
00351
00352 Point3f axis = dest ^ source;
00353 float sinangle = axis.Norm();
00354 float cosangle = dest.dot(source);
00355 float angle = math::Atan2(sinangle,cosangle);
00356
00357 if( math::Abs(angle) < EPSILON )
00358 return;
00359
00360 if( math::Abs(math::Abs(angle)-M_PI) < EPSILON){
00361
00362 Plane3f plane(0,source);
00363 axis=plane.Projection(Point3f(1,0,0));
00364 if(axis.Norm() < EPSILON){
00365 axis=plane.Projection(Point3f(0,1,0));
00366 assert(axis.Norm() > EPSILON);
00367 }
00368 }
00369 rotation = rotation * Quaternionf(angle,axis);
00370 }