NDTVizGlut.hh
Go to the documentation of this file.
00001 #ifndef NDTVIZGLUT_HH
00002 #define NDTVIZGLUT_HH
00003 
00004 #include <GL/freeglut.h>
00005 #include <vector>
00006 #include <string>
00007 #include <math.h>
00008 #include <iostream>
00009 #include <deque>
00010 #include <Eigen/Core>
00011 #include <Eigen/Eigenvalues> 
00012 #include <boost/thread.hpp>
00013  #include <assert.h>
00014  #include <unistd.h>
00015  #include <math.h>
00016  #include <iostream>
00017 
00018 inline void checkOpenGLError()
00019 {
00020   int    openglErr;
00021   if ( ( openglErr= glGetError()) != GL_NO_ERROR )
00022     {
00023       const std::string sErr = std::string("OpenGL error: ") + std::string( (char*)gluErrorString(openglErr) );
00024       std::cerr << "[checkOpenGLError] " << sErr << std::endl;
00025     }
00026 }
00027 
00028 // typedef struct
00029 // {
00030 //      float x;
00031 //      float y;
00032 // } glut3d_vector2_t;
00033 
00034 // typedef struct
00035 // {
00036 //      float x;
00037 //      float y;
00038 //      float z;
00039 // } glut3d_vector3_t;
00040 
00041 
00042 static int win;
00043 
00044 //static void * glthread( void * pParam );
00045 void * glthread( void * pParam );
00046 
00047 
00048 static int create_gl_thread( void ) {
00049     
00050   pthread_t thread1;
00051      
00052   int iRet = pthread_create( &thread1, NULL, glthread, NULL );
00053      
00054   return iRet;
00055 }
00056 
00057 
00058 class NDTVizGlutColorPoint {
00059 public:
00060   NDTVizGlutColorPoint() { }
00061   NDTVizGlutColorPoint(float x, float y, float z, float R, float G, float B) {
00062     pos[0] = x; pos[1] = y; pos[2] = z;
00063     col[0] = R; col[1] = G; col[2] = B;
00064   }
00065   GLfloat pos[3];
00066   GLfloat col[3];
00067 };
00068 
00069 class NDTVizGlutLine {
00070 public:
00071   NDTVizGlutLine() { }
00072   NDTVizGlutLine(float x1, float y1, float z1, float x2, float y2, float z2) {
00073     pos1[0] = x1; pos1[1] = y1; pos1[2] = z1;
00074     pos2[0] = x2; pos2[1] = y2; pos2[2] = z2;
00075   }
00076   GLfloat pos1[3];
00077   GLfloat pos2[3];
00078 };
00079 
00080 class NDTVizGlutColor4f {
00081 public:
00082   GLfloat R,G,B,A;
00083 };
00084 
00086 class NDTVizGlutObject
00087 {
00088 public:
00090   virtual void draw() = 0;
00091 };
00092 
00093 class NDTVizGlutPointCloudColor : public NDTVizGlutObject
00094 {
00095 public:
00096   NDTVizGlutPointCloudColor() {
00097         
00098   }
00099   void draw() {
00100     glBegin(GL_POINTS);
00101     //glPointSize( m_pointSize );
00102     for (size_t i = 0; i < pts.size(); i++) {
00103       glColor3fv(pts[i].col);
00104       glVertex3fv(pts[i].pos);
00105     }
00106     glEnd();
00107         checkOpenGLError();
00108   }
00109   void setPointSize(float size) { m_pointSize = size; }
00110   void clear() { pts.clear(); }
00111   void push_back(float x, float y, float z, float R, float G, float B) {
00112     pts.push_back(NDTVizGlutColorPoint(x,y,z,R,G,B));
00113   }
00114   NDTVizGlutColorPoint& getPoint(size_t i) { return pts[i]; }
00115 private:
00116   float m_pointSize;
00117   std::vector<NDTVizGlutColorPoint> pts;
00118 };
00119 
00120 class NDTVizGlutSetOfLines : public NDTVizGlutObject
00121 {
00122 public:
00123   NDTVizGlutSetOfLines() {
00124     setColor4(1.0, 0.4, 0.0, 0.8);
00125     m_antiAliasing = true;
00126   }
00127   void draw() {
00128 
00129         glPushAttrib( GL_COLOR_BUFFER_BIT | GL_LINE_BIT );
00130         if (m_antiAliasing)
00131       glEnable(GL_LINE_SMOOTH);
00132     //  glLineWidth(m_lineWidth);
00133         checkOpenGLError();
00134 
00135         glDisable(GL_LIGHTING);  // Disable lights when drawing lines
00136         glBegin(GL_LINES);
00137         glColor4f(m_color.R,m_color.G,m_color.B,m_color.A);
00138         for (size_t i = 0; i < lines.size(); i++)
00139       {
00140         glVertex3fv(lines[i].pos1);
00141                 glVertex3fv(lines[i].pos2);
00142       }
00143         glEnd();
00144         checkOpenGLError();
00145         glEnable(GL_LIGHTING);  // Disable lights when drawing lines
00146 
00147         // End of antialiasing:
00148     glPopAttrib();
00149   }
00150   void setPointSize(float size) { m_pointSize = size; }
00151   void clear() { lines.clear(); }
00152   void push_back(float x1, float y1, float z1, float x2, float y2, float z2) {
00153     lines.push_back(NDTVizGlutLine(x1, y1, z1, x2, y2, z2));
00154   }
00155   void appendLine(float x1, float y1, float z1, float x2, float y2, float z2) {
00156     this->push_back(x1, y1, z1, x2, y2, z2);
00157   }
00158   NDTVizGlutLine& getLine(size_t i) { return lines[i]; }
00159   void setColor(float R, float G, float B) { 
00160     m_color.R = R;
00161     m_color.G = G;
00162     m_color.B = B;
00163   }
00164   void setColor4(float R, float G, float B, float A) {
00165     m_color.R = R; m_color.G = G; m_color.B = B; m_color.A = A;
00166   }
00167 
00168 private:
00169   float m_lineWidth;
00170   NDTVizGlutColor4f m_color;
00171   bool m_antiAliasing;
00172   float m_pointSize;
00173   std::vector<NDTVizGlutLine> lines;
00174 };
00175 
00176 
00177 
00178 class NDTVizGlutEllipsoid : public NDTVizGlutObject
00179 {
00180 public:
00181   NDTVizGlutEllipsoid() {
00182     m_quantiles = 3;
00183     m_lineWidth = 1;;
00184     m_drawSolid3D = true;
00185     m_3D_segments = 20;
00186     this->setColor4(0.5, 1.0, 0.1, 0.8);
00187   }
00188   NDTVizGlutEllipsoid(float quantiles, float lineWidth, bool drawSolid, int segments) {
00189     m_quantiles = quantiles;
00190     m_lineWidth = lineWidth;
00191     m_drawSolid3D = drawSolid;
00192     m_3D_segments = segments;
00193     this->setColor4(0.5, 1.0, 0.1, 0.8);
00194   }
00195   ~NDTVizGlutEllipsoid() { }
00196   void setLocation(double x, double y, double z) { 
00197     Eigen::Vector3d p(x,y,z);
00198     this->setPos(p);
00199   }
00200   void enableDrawSolid3D(bool s) { m_drawSolid3D = s; }
00201   void setPos(const Eigen::Vector3d &pos) { m_mean = pos; }
00202   void setCovMatrix(const Eigen::Matrix3d &cov) { this->setCov(cov); }
00203   void setCov(const Eigen::Matrix3d &cov) {
00204     m_cov = cov;
00205     const double d=m_cov.determinant();
00206         if (d==0 || d!=d) // Note: "d!=d" is a great test for invalid numbers, don't remove!
00207       {
00208         // All zeros:
00209         m_prevComputedCov = m_cov;
00210         m_eigVec = Eigen::Matrix3d::Zero(3,3);
00211         m_eigVal = Eigen::Matrix3d::Zero(3,3);
00212       }
00213         else
00214       {
00215         // Not null matrix: compute the eigen-vectors & values:
00216         m_prevComputedCov = m_cov;
00217         Eigen::EigenSolver<Eigen::Matrix3d> es(m_cov);
00218         //m_eigVal = es.eigenvalues();
00219         //m_eigVec = es.eigenvectors();
00220 
00221         m_eigVal = es.pseudoEigenvalueMatrix();
00222         m_eigVec = es.pseudoEigenvectors();
00223             
00224         m_eigVal = m_eigVal.cwiseSqrt();
00225         // Do the scale at render to avoid recomputing the m_eigVal for different m_quantiles
00226       }
00227 
00228   }
00229 
00230   void setColor4(float R, float G, float B, float A) {
00231     m_color.R = R; m_color.G = G; m_color.B = B; m_color.A = A;
00232   }
00233 
00234   void setColor(float R, float G, float B, float A) { setColor4(R, G, B, A); }
00235 
00236   void draw() {
00237     glPushMatrix();
00238     glTranslatef(m_mean(0), m_mean(1), m_mean(2));
00239 
00240     const size_t dim = m_cov.cols();
00241     if(m_eigVal(0,0) != 0.0 && m_eigVal(1,1) != 0.0 && (dim==2 || m_eigVal(2,2) != 0.0) && m_quantiles!=0.0)
00242       {
00243                 glEnable(GL_BLEND);
00244                 checkOpenGLError();
00245         glColor4f(m_color.R, m_color.G, m_color.B, m_color.A);
00246                 
00247                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00248                 checkOpenGLError();
00249         glLineWidth(m_lineWidth);
00250                 checkOpenGLError();
00251 
00252                 if (dim==2)
00253           {
00254                         // // ---------------------
00255                         // //     2D ellipse
00256                         // // ---------------------
00257 
00258                         // /* Equivalent MATLAB code: 
00259                         //  *
00260                         //  * q=1;
00261                         //  * [vec val]=eig(C); 
00262                         //  * M=(q*val*vec)';  
00263                         //  * R=M*[x;y];
00264                         //  * xx=R(1,:);yy=R(2,:);  
00265                         //  * plot(xx,yy), axis equal;
00266                         //  */
00267 
00268                         // double                       ang;
00269                         // unsigned int i;
00270 
00271                         // // Compute the new vectors for the ellipsoid:
00272             // Eigen::Matrix3d  M;
00273                         // M.noalias() = double(m_quantiles) * m_eigVal * m_eigVec.adjoint();
00274 
00275                         // glBegin( GL_LINE_LOOP );
00276 
00277                         // // Compute the points of the 2D ellipse:
00278                         // for (i=0,ang=0;i<m_2D_segments;i++,ang+= (M_2PI/m_2D_segments))
00279                         // {
00280                         //      double ccos = cos(ang);
00281                         //      double ssin = sin(ang);
00282 
00283                         //      const float x = ccos * M.get_unsafe(0,0) + ssin * M.get_unsafe(1,0);
00284                         //      const float y = ccos * M.get_unsafe(0,1) + ssin * M.get_unsafe(1,1);
00285 
00286                         //      glVertex2f( x,y );
00287                         // } // end for points on ellipse
00288 
00289                         // glEnd();
00290           }
00291                 else
00292           {
00293                         // ---------------------
00294                         //    3D ellipsoid
00295                         // ---------------------
00296                         GLfloat         mat[16];
00297 
00298                         //  A homogeneous transformation matrix, in this order:
00299                         //
00300                         //     0  4  8  12
00301                         //     1  5  9  13
00302                         //     2  6  10 14
00303                         //     3  7  11 15
00304                         //
00305                         mat[3] = mat[7] = mat[11] = 0;
00306                         mat[15] = 1;
00307                         mat[12] = mat[13] = mat[14] = 0;
00308 
00309                         mat[0] = m_eigVec(0,0); mat[1] = m_eigVec(1,0); mat[2] = m_eigVec(2,0); // New X-axis
00310                         mat[4] = m_eigVec(0,1); mat[5] = m_eigVec(1,1); mat[6] = m_eigVec(2,1); // New X-axis
00311                         mat[8] = m_eigVec(0,2); mat[9] = m_eigVec(1,2); mat[10] = m_eigVec(2,2);        // New X-axis
00312 
00313                         glDisable(GL_LIGHTING);
00314                         //glEnable(GL_LIGHTING);
00315                         //glEnable(GL_LIGHT0);
00316                         glEnable(GL_COLOR_MATERIAL);
00317                         glShadeModel(GL_SMOOTH);
00318 
00319                         GLUquadricObj   *obj = gluNewQuadric();
00320                         checkOpenGLError();
00321 
00322                         gluQuadricDrawStyle( obj, m_drawSolid3D ? GLU_FILL : GLU_LINE);
00323 
00324                         glPushMatrix();
00325                         glMultMatrixf( mat );
00326             glScalef(m_eigVal(0,0)*m_quantiles,m_eigVal(1,1)*m_quantiles,m_eigVal(2,2)*m_quantiles);
00327 
00328                         gluSphere( obj, 1,m_3D_segments,m_3D_segments);
00329                         checkOpenGLError();
00330 
00331                         glPopMatrix();
00332 
00333                         gluDeleteQuadric(obj);
00334                         checkOpenGLError();
00335 
00336                         glDisable(GL_LIGHTING);
00337                         glDisable(GL_LIGHT0);
00338 
00339 
00340           }
00341 
00342 
00343         glLineWidth(1.0f);
00344                 glDisable(GL_BLEND);
00345 
00346       }
00347     glPopMatrix();
00348   }
00349 private:
00350   Eigen::Matrix3d m_cov, m_prevComputedCov, m_eigVal, m_eigVec;
00351   Eigen::Vector3d m_mean;
00352   NDTVizGlutColor4f m_color;
00353   float m_quantiles;
00354   float m_lineWidth;
00355   bool m_drawSolid3D;
00356   int m_3D_segments;
00357 public:
00358   EIGEN_MAKE_ALIGNED_OPERATOR_NEW  
00359 };
00360 
00361 
00362 class NDTVizGlutEllipsoids : public NDTVizGlutObject {
00363 public:
00364   void draw() {
00365     for (size_t i = 0; i < objs.size(); i++) {
00366       objs[i].draw();
00367     }
00368   }
00369   void push_back(const NDTVizGlutEllipsoid &obj) { objs.push_back(obj); }
00370   void clear() { objs.clear(); objs.resize(0); }
00371 private:
00372   std::vector<NDTVizGlutEllipsoid, Eigen::aligned_allocator<NDTVizGlutEllipsoid> > objs;
00373 };
00374 
00376 class NDTVizGlutCamera {
00377 public:
00378   virtual Eigen::Vector3f getPosition() const = 0;
00379   virtual Eigen::Vector3f getFocalPoint() const = 0;
00380   virtual Eigen::Vector3f getUpVector() const = 0;
00381   virtual void setFocalPoint(const Eigen::Vector3f &fp) = 0;
00382 };
00383 
00385 class NDTVizGlutXYOrbitCamera : public NDTVizGlutCamera {
00386 private: 
00387   int last_button_;
00388   int last_state_;
00389   Eigen::Vector2i last_point_;
00390   Eigen::Vector3f focal_point_;
00391   float distance;
00392   float yaw;
00393   float pitch;
00394 public:
00395   NDTVizGlutXYOrbitCamera() {
00396     last_button_ = -1; 
00397     last_state_ = -1;
00398     distance = 30.;
00399     yaw = 1.;
00400     pitch = 0.7;
00401     focal_point_ = Eigen::Vector3f(0., 0., 0.);
00402   }
00403 
00404   Eigen::Vector3f getPosition() const {
00405     Eigen::Vector3f p = Eigen::Vector3f(
00406                                         cos(yaw)*cos(pitch)*distance,
00407                                         sin(yaw)*cos(pitch)*distance,
00408                                         sin(pitch)*distance);
00409     return p + getFocalPoint();
00410   }
00411   Eigen::Vector3f getFocalPoint() const {
00412     return focal_point_;
00413   }
00414   void setFocalPoint(const Eigen::Vector3f &fp) {
00415     focal_point_ = fp;
00416   }
00417   Eigen::Vector3f getUpVector() const {
00418     return Eigen::Vector3f(0., 0., 1.);
00419   }
00420   float getPitchAngle() const { return pitch; }
00421   void setPitchAngle(double p) { pitch = p; } 
00422   void update_mouse(int button, int state, int x, int y) {
00423     last_button_ = button;
00424     last_state_ = state;
00425     last_point_[0] = x;
00426     last_point_[1] = y;
00427 
00428     // Wheel reports as button 3(scroll up) and button 4(scroll down)
00429     if ((button == 3) || (button == 4)) // It's a wheel event
00430       {
00431         // Each wheel event reports like a button click, GLUT_DOWN then GLUT_UP
00432         if (state != GLUT_UP) { // Disregard redundant GLUT_UP events
00433           if (button == 3) 
00434             distance *= 0.9;
00435           else
00436             distance *= 1.1;
00437         }
00438       }       
00439         
00440   }
00441   void update_motion(int x, int y) {
00442     // Left button in x -> change the yaw
00443     // Middle button -> move the position in x-dir,y-dir.
00444     // Rigth button in y -> move the position along z-dir.
00445     float dx = (x - last_point_[0])*0.01;
00446     float dy = (y - last_point_[1])*0.01;
00447     switch(last_button_) {
00448     case GLUT_LEFT_BUTTON:
00449       yaw += -dx;
00450       pitch += dy;
00451       if (pitch > M_PI/2.)
00452         pitch = M_PI/2.- 0.0001;
00453       if (pitch < -M_PI/2.)
00454         pitch = -M_PI/2.+ 0.0001;
00455       break;
00456     case GLUT_MIDDLE_BUTTON:
00457       dx *= distance*0.15;
00458       dy *= distance*0.15;
00459       focal_point_[1] += -cos(-yaw) * dx -sin(yaw) * dy;
00460       focal_point_[0] += -sin(-yaw) * dx -cos(yaw) * dy;
00461       //focal_point_[1] -= cos(yaw) * dx; // - sin(yaw) * dy;
00462       break;
00463     case GLUT_RIGHT_BUTTON:
00464       if (dy > 0)
00465         distance *= 1.05;
00466       else
00467         distance *= 0.95;
00468       break;
00469     default:
00470       break;
00471     };
00472     last_point_[0] = x;
00473     last_point_[1] = y;
00474   }
00475 };
00476 
00477 
00479 
00483 class NDTVizGlut {
00484 public:
00486   NDTVizGlut();
00488   virtual ~NDTVizGlut();
00490   virtual int win_run(int *argc, char **argv);
00492   virtual void win_key(unsigned char key, int x, int y);
00494   virtual void win_mouse(int button, int state, int x, int y);
00496   virtual void win_motion(int x, int y);
00498   virtual void win_reshape(int width, int height);
00500   virtual void win_redraw();
00502   virtual void win_idle();
00504   virtual void win_close();
00506   virtual void process_events();
00507 
00508   virtual void start_main_loop() {
00509     glutMainLoop();
00510   }
00511 
00512   virtual void start_main_loop_own_thread() {
00513     // boost::thread workerThread(workerFunc);
00514     create_gl_thread();
00515     // if(pthread_create(&glut_event_processing_thread, NULL, ndt_viz_event_loop_thread, this)) {
00516             
00517     //     std::cerr << "Error creating thread\n";
00518     // }
00519   }
00520 
00521 
00522   virtual void draw_origin();
00523 
00525   int save(const std::string &fileName);
00526 
00528   void set_save_inc_flag(bool flag) { do_save_inc = flag; }
00529 
00531   void addObject(NDTVizGlutObject* object) {
00532     objects.push_back(object);
00533   }
00534      
00536   //     void setDrawingStyle();
00537 
00539   void repaint();
00540 
00541   void clearScene();
00542 
00543   void setCameraPointingToPoint(double x, double y, double z);
00544   void setCameraPosition(double x, double y, double z); //Not used?
00545 
00546   bool isOpen() const;
00547 
00548   bool keyHit() const;
00549   unsigned char getPushedKey();
00550 
00551   void update_cam();
00552 
00553 
00554 protected:
00556 
00560   virtual void draw();
00561 
00562   void cam_rotate();
00563 
00565   int save_inc();
00566 
00567 
00568   pthread_t glut_event_processing_thread;
00569 
00570   // GUI settings
00571   //     int win;
00572   int gui_pause;
00573   //     int viewport_width;
00574   //     int viewport_height;
00575   int show_samples;
00576   int show_grid;
00577 
00578   double start_time;
00579 
00580   Eigen::Vector3f cam_pos;
00581   Eigen::Vector3f cam_dir;
00582 
00583   float cam_radius;
00584   float cam_sweep_ang;
00585   float cam_azim;
00586      
00587   float cam_sweep_speed;
00588 
00589   bool cam_sweep;
00590 
00591   int save_inc_counter;
00592   bool do_save_inc;
00593 
00594   bool open;
00595 
00596   // // Objects to draw
00597   std::vector<NDTVizGlutObject*> objects;
00598   NDTVizGlutXYOrbitCamera camera;
00599 
00600   std::deque<unsigned char> pressed_keys;
00601 };
00602 
00604 
00605 // // // Needed for the wrapper calls.
00606 // static NDTVizGlut* glut3d_ptr = 0x0;
00607 
00608 // // Need some wrapper functions to handle the callbacks functions.
00609 // void win_reshape_(int w, int h) { glut3d_ptr->win_reshape (w,h); } 
00610 // void win_redraw_() { glut3d_ptr->win_redraw(); }
00611 // void win_key_(unsigned char key, int x, int y) { glut3d_ptr->win_key(key, x, y); }
00612 // void win_mouse_(int button, int state, int x, int y) { glut3d_ptr->win_mouse(button, state, x, y); }
00613 // void win_motion_(int x, int y) { glut3d_ptr->win_motion(x, y); }
00614 // void win_idle_() { glut3d_ptr->win_idle(); }  
00615 // void win_close_() { glut3d_ptr->win_close(); }
00616 
00617 // void * glthread(void * pParam)
00618 // {
00619 //   int argc=0;
00620 //   char** argv = NULL;
00621               
00622 //   glutInit(&argc, argv);
00623           
00624 //   // Create a window
00625 //   glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
00626 //   glutInitWindowSize(640,480);
00627      
00628 //   win = glutCreateWindow("NDTVizGlut");
00629      
00630 //   glEnable(GL_DEPTH_TEST);
00631      
00632 //   glEnable(GL_LIGHTING);
00633 //   glEnable(GL_LIGHT0);
00634      
00635 //   // Create light components
00636 //   GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
00637 //   GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8, 1.0f };
00638 //   GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
00639 //   GLfloat position[] = { -1.5f, 1.0f, -4.0f, 1.0f };
00640      
00641 //   // Assign created components to GL_LIGHT0
00642 //   glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
00643 //   glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
00644 //   glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
00645 //   glLightfv(GL_LIGHT0, GL_POSITION, position);
00646 
00647 
00648 //   // enable color tracking
00649 //   glEnable(GL_COLOR_MATERIAL);
00650 //   // set material properties which will be assigned by glColor
00651 //   glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
00652 
00653 
00654 //   glutReshapeFunc(win_reshape_);
00655 //   glutDisplayFunc(win_redraw_);
00656 //   glutKeyboardFunc(win_key_);
00657 //   glutMouseFunc(win_mouse_);
00658 //   glutMotionFunc(win_motion_);
00659 //   glutPassiveMotionFunc(NULL);
00660 
00661 //   // Idle loop callback
00662 //   glutIdleFunc(win_idle_);
00663 
00664 //   // Window close function
00665 //   glutCloseFunc(win_close_);
00666 //   /* Thread will loop here */
00667 
00668 //   while (true) {
00669 //     usleep(1000);
00670 //     for (int i = 0; i < 10; i++)
00671 //       glutMainLoopEvent();
00672 //     glut3d_ptr->update_cam();
00673 //     win_redraw_();
00674 //   }
00675 //   //glutMainLoop();
00676      
00677 //   return NULL;
00678 // }
00679 
00680 #endif


ndt_visualisation
Author(s): Todor Stoyanov, Jari Saarinen, Henrik Andreasson
autogenerated on Wed Aug 26 2015 15:24:57