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
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 static int win;
00043
00044
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
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
00133 checkOpenGLError();
00134
00135 glDisable(GL_LIGHTING);
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);
00146
00147
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)
00207 {
00208
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
00216 m_prevComputedCov = m_cov;
00217 Eigen::EigenSolver<Eigen::Matrix3d> es(m_cov);
00218
00219
00220
00221 m_eigVal = es.pseudoEigenvalueMatrix();
00222 m_eigVec = es.pseudoEigenvectors();
00223
00224 m_eigVal = m_eigVal.cwiseSqrt();
00225
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
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 }
00291 else
00292 {
00293
00294
00295
00296 GLfloat mat[16];
00297
00298
00299
00300
00301
00302
00303
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);
00310 mat[4] = m_eigVec(0,1); mat[5] = m_eigVec(1,1); mat[6] = m_eigVec(2,1);
00311 mat[8] = m_eigVec(0,2); mat[9] = m_eigVec(1,2); mat[10] = m_eigVec(2,2);
00312
00313 glDisable(GL_LIGHTING);
00314
00315
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
00429 if ((button == 3) || (button == 4))
00430 {
00431
00432 if (state != GLUT_UP) {
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
00443
00444
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
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
00514 create_gl_thread();
00515
00516
00517
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
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);
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
00571
00572 int gui_pause;
00573
00574
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
00597 std::vector<NDTVizGlutObject*> objects;
00598 NDTVizGlutXYOrbitCamera camera;
00599
00600 std::deque<unsigned char> pressed_keys;
00601 };
00602
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680 #endif