00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "ros/ros.h"
00019 #include <QtGui>
00020 #include <QtOpenGL>
00021 #include <QThread>
00022 #include <GL/gl.h>
00023 #include <GL/glut.h>
00024 #include "boost/foreach.hpp"
00025 #include <cmath>
00026 #ifdef GL2PS
00027 #include <gl2ps.h>
00028 #endif
00029 #include "glviewer.h"
00030
00031 #ifndef GL_MULTISAMPLE
00032 #define GL_MULTISAMPLE 0x809D
00033 #endif
00034
00035 const double PI= 3.14159265358979323846;
00036
00037 template <typename PointType>
00038 inline bool validXYZ(const PointType& p){
00039 return std::isfinite(p.x) && std::isfinite(p.y) && std::isfinite(p.z);
00040 };
00041
00042 GLViewer::GLViewer(QWidget *parent)
00043 : QGLWidget(QGLFormat(QGL::SampleBuffers|QGL::StereoBuffers), parent),
00044 xRot(180*16.0),
00045 yRot(0),
00046 zRot(0),
00047 xTra(0),
00048 yTra(0),
00049 zTra(-50),
00050 polygon_mode(GL_FILL),
00051 cloud_list_indices(),
00052 edge_list_(NULL),
00053 cloud_matrices(new QList<QMatrix4x4>()),
00054 show_poses_(ParameterServer::instance()->get<bool>("show_axis")),
00055 show_ids_(false),
00056 show_edges_(ParameterServer::instance()->get<bool>("show_axis")),
00057 show_clouds_(true),
00058 follow_mode_(true),
00059 stereo_(false),
00060 width_(0),
00061 height_(0),
00062 stereo_shift_(0.1),
00063 fov_(100.0/180.0*PI),
00064 rotation_stepping_(1.0)
00065 {
00066 bg_col_[0] = bg_col_[1] = bg_col_[2] = bg_col_[3] = 0.0;
00067 ROS_DEBUG_COND(!this->format().stereo(), "Stereo not supported");
00068 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00069 viewpoint_tf_.setToIdentity();
00070 }
00071
00072 GLViewer::~GLViewer() { }
00073
00074 QSize GLViewer::minimumSizeHint() const {
00075 return QSize(400, 400);
00076 }
00077
00078 QSize GLViewer::sizeHint() const {
00079 return QSize(640, 480);
00080 }
00081
00082 static void qNormalizeAngle(int &angle) {
00083 while (angle < 0)
00084 angle += 360 * 16;
00085 while (angle > 360 * 16)
00086 angle -= 360 * 16;
00087 }
00088
00089 void GLViewer::setXRotation(int angle) {
00090 qNormalizeAngle(angle);
00091 if (angle != xRot) {
00092 xRot = angle;
00093 updateGL();
00094 }
00095 }
00096
00097
00098 void GLViewer::setYRotation(int angle) {
00099 qNormalizeAngle(angle);
00100 if (angle != yRot) {
00101 yRot = angle;
00102 updateGL();
00103 }
00104 }
00105
00106 void GLViewer::setRotationGrid(double rot_step_in_degree) {
00107 rotation_stepping_ = rot_step_in_degree;
00108 }
00109
00110 void GLViewer::setStereoShift(double shift) {
00111 stereo_shift_ = shift;
00112 updateGL();
00113 }
00114
00115 void GLViewer::setZRotation(int angle) {
00116 qNormalizeAngle(angle);
00117 if (angle != zRot) {
00118 zRot = angle;
00119 updateGL();
00120 }
00121 }
00122
00123 void GLViewer::initializeGL() {
00124 glClearColor(bg_col_[0],bg_col_[1],bg_col_[2],bg_col_[3]);
00125 glEnable (GL_BLEND);
00126 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00127 glEnable(GL_DEPTH_TEST);
00128 glEnable(GL_CULL_FACE);
00129 glEnable(GL_LINE_SMOOTH);
00130
00131
00132
00133
00134
00136
00137
00138 }
00139
00140 inline
00141 void GLViewer::drawTriangle(const point_type& p1, const point_type& p2, const point_type& p3){
00142 unsigned char b,g,r;
00143 b = *( (unsigned char*)(&p1.rgb));
00144 g = *(1+(unsigned char*)(&p1.rgb));
00145 r = *(2+(unsigned char*)(&p1.rgb));
00146 glColor3ub(r,g,b);
00147 glColor3ub(255,0,0);
00148 glVertex3f(p1.x, p1.y, p1.z);
00149
00150 b = *( (unsigned char*)(&p2.rgb));
00151 g = *(1+(unsigned char*)(&p2.rgb));
00152 r = *(2+(unsigned char*)(&p2.rgb));
00153 glColor3ub(r,g,b);
00154 glColor3ub(0,255,0);
00155 glVertex3f(p2.x, p2.y, p2.z);
00156
00157 b = *( (unsigned char*)(&p3.rgb));
00158 g = *(1+(unsigned char*)(&p3.rgb));
00159 r = *(2+(unsigned char*)(&p3.rgb));
00160
00161 glColor3ub(0,0,255);
00162 glVertex3f(p3.x, p3.y, p3.z);
00163 }
00164
00165 void GLViewer::drawAxis(float scale){
00166 glBegin(GL_LINES);
00167 glLineWidth(4);
00168 glColor4f (0.9, 0, 0, 1.0);
00169 glVertex3f(0, 0, 0);
00170 glColor4f (0.9, 0, 0, 0.0);
00171 glVertex3f(scale, 0, 0);
00172 glColor4f (0, 0.9, 0, 1.0);
00173 glVertex3f(0, 0, 0);
00174 glColor4f (0, 0.9, 0, 0.0);
00175 glVertex3f(0, scale, 0);
00176 glColor4f (0, 0, 0.9, 1.0);
00177 glVertex3f(0, 0, 0);
00178 glColor4f (0, 0, 0.9, 0.0);
00179 glVertex3f(0, 0, scale);
00180 glEnd();
00181 }
00182
00183 void GLViewer::paintGL() {
00184 if(!this->isVisible()) return;
00185
00186 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00187 if(stereo_){
00188 float ratio = (float)(width_) / (float) height_;
00189 glViewport(0, 0, width_/2, height_);
00190 glMatrixMode(GL_PROJECTION);
00191 glLoadIdentity();
00192 gluPerspective(fov_, ratio, 0.1, 1e4);
00193 glMatrixMode(GL_MODELVIEW);
00194 drawClouds(stereo_shift_);
00195
00196 glViewport(width_/2, 0, width_/2, height_);
00197 glMatrixMode(GL_PROJECTION);
00198 glLoadIdentity();
00199 gluPerspective(fov_, ratio, 0.1, 1e4);
00200 glMatrixMode(GL_MODELVIEW);
00201 }
00202 drawClouds(0.0);
00203 }
00204
00205 void GLViewer::drawClouds(float xshift) {
00206 if(follow_mode_){
00207 int id = cloud_matrices->size()-1;
00208 if(id >= 0)setViewPoint((*cloud_matrices)[id]);
00209 }
00210 glLoadIdentity();
00211
00212 glTranslatef(xTra+xshift, yTra, zTra);
00213 int x_steps = (xRot / 16.0)/rotation_stepping_;
00214 int y_steps = (yRot / 16.0)/rotation_stepping_;
00215 int z_steps = (zRot / 16.0)/rotation_stepping_;
00216 glRotatef(x_steps*rotation_stepping_, 1.0, 0.0, 0.0);
00217 glRotatef(y_steps*rotation_stepping_, 0.0, 1.0, 0.0);
00218 glRotatef(z_steps*rotation_stepping_, 0.0, 0.0, 1.0);
00219 glMultMatrixd(static_cast<GLdouble*>( viewpoint_tf_.data() ));
00220 ROS_DEBUG("Drawing %i PointClouds", cloud_list_indices.size());
00221 for(int i = 0; i<cloud_list_indices.size() && i<cloud_matrices->size(); i++){
00222
00223
00224
00225
00226 glPushMatrix();
00227 glMultMatrixd(static_cast<GLdouble*>( (*cloud_matrices)[i].data() ));
00228 if(show_clouds_) glCallList(cloud_list_indices[i]);
00229 if(show_poses_) drawAxis(0.075);
00230 if(show_ids_) {
00231 glColor4f(1-bg_col_[0],1-bg_col_[1],1-bg_col_[2],1.0);
00232 this->renderText(0.,0.,0.,QString::number(i));
00233 }
00234 glPopMatrix();
00235 }
00236 if(show_poses_) drawAxis(0.2);
00237 if(show_edges_) drawEdges();
00238 }
00239
00240 void GLViewer::resizeGL(int width, int height)
00241 {
00242 width_ = width;
00243 height_ = height;
00244
00245 glViewport(0, 0, width, height);
00246
00247
00248 glMatrixMode(GL_PROJECTION);
00249 glLoadIdentity();
00250
00251
00252
00253
00254
00255
00256 float ratio = (float)width / (float) height;
00257 gluPerspective(fov_, ratio, 0.1, 1e4);
00258 glMatrixMode(GL_MODELVIEW);
00259 }
00260
00261 void GLViewer::mouseDoubleClickEvent(QMouseEvent *event) {
00262 xRot=180*16.0;
00263 yRot=0;
00264 zRot=0;
00265 xTra=0;
00266 yTra=0;
00267 if(cloud_matrices->size()>0){
00268 if(!setClickedPosition(event->x(), event->y())){
00269 if (event->buttons() & Qt::LeftButton) {
00270 int id = cloud_matrices->size()-1;
00271 setViewPoint((*cloud_matrices)[id]);
00272 } else if (event->buttons() & Qt::RightButton) {
00273 int id = 0;
00274 setViewPoint((*cloud_matrices)[id]);
00275 } else if (event->buttons() & Qt::MidButton) {
00276 viewpoint_tf_.setToIdentity();
00277 zTra=-50;
00278 }
00279 }
00280 }
00281 updateGL();
00282 }
00283 void GLViewer::toggleStereo(bool flag){
00284 stereo_ = flag;
00285 resizeGL(width_, height_);
00286 updateGL();
00287 }
00288 void GLViewer::toggleBackgroundColor(bool flag){
00289 if(flag){
00290 bg_col_[0] = bg_col_[1] = bg_col_[2] = bg_col_[3] = 0.0;
00291 }
00292 else{
00293 bg_col_[0] = bg_col_[1] = bg_col_[2] = 1.0;
00294 }
00295 glClearColor(bg_col_[0],bg_col_[1],bg_col_[2],bg_col_[3]);
00296 updateGL();
00297 }
00298 void GLViewer::toggleShowClouds(bool flag){
00299 show_clouds_ = flag;
00300 updateGL();
00301 }
00302 void GLViewer::toggleShowIDs(bool flag){
00303 show_ids_ = flag;
00304 updateGL();
00305 }
00306 void GLViewer::toggleShowEdges(bool flag){
00307 show_edges_ = flag;
00308 updateGL();
00309 }
00310 void GLViewer::toggleShowPoses(bool flag){
00311 show_poses_ = flag;
00312 updateGL();
00313 }
00314 void GLViewer::toggleFollowMode(bool flag){
00315 follow_mode_ = flag;
00316 }
00317 void GLViewer::mousePressEvent(QMouseEvent *event) {
00318 lastPos = event->pos();
00319 }
00320
00321 void GLViewer::wheelEvent(QWheelEvent *event) {
00322 zTra += ((float)event->delta())/25.0;
00323 updateGL();
00324 }
00325 void GLViewer::mouseMoveEvent(QMouseEvent *event) {
00326 int dx = event->x() - lastPos.x();
00327 int dy = event->y() - lastPos.y();
00328
00329 if (event->buttons() & Qt::LeftButton) {
00330 setXRotation(xRot - 8 * dy);
00331 setYRotation(yRot + 8 * dx);
00332 } else if (event->buttons() & Qt::RightButton) {
00333 setXRotation(xRot - 8 * dy);
00334 setZRotation(zRot + 8 * dx);
00335 } else if (event->buttons() & Qt::MidButton) {
00336 xTra += dx/200.0;
00337 yTra -= dy/200.0;
00338 updateGL();
00339 }
00340 lastPos = event->pos();
00341 }
00342
00343 void GLViewer::updateTransforms(QList<QMatrix4x4>* transforms){
00344 ROS_WARN_COND(transforms->size() < cloud_matrices->size(), "Got less transforms than before!");
00345
00346 delete cloud_matrices;
00347 cloud_matrices = transforms;
00348 ROS_DEBUG("New Cloud matrices size: %d", cloud_matrices->size());
00349 updateGL();
00350 }
00351
00352 void GLViewer::addPointCloud(pointcloud_type * pc, QMatrix4x4 transform){
00353 ROS_DEBUG("pc pointer in addPointCloud: %p (this is %p in thread %d)", pc, this, (unsigned int)QThread::currentThreadId());
00354 pointCloud2GLStrip(pc);
00355 cloud_matrices->push_back(transform);
00356 updateGL();
00357 }
00358
00359 void GLViewer::pointCloud2GLStrip(pointcloud_type * pc){
00360 struct timespec starttime, finish; double elapsed; clock_gettime(CLOCK_MONOTONIC, &starttime);
00361 ROS_DEBUG("Making GL list from point-cloud pointer %p in thread %d", pc, (unsigned int)QThread::currentThreadId());
00362 GLuint cloud_list_index = glGenLists(1);
00363 if(!cloud_list_index) {
00364 ROS_ERROR("No display list could be created");
00365 return;
00366 }
00367 float mesh_thresh = ParameterServer::instance()->get<double>("squared_meshing_threshold");
00368 glNewList(cloud_list_index, GL_COMPILE);
00369 cloud_list_indices.push_back(cloud_list_index);
00370
00371 point_type origin;
00372 origin.x = 0;
00373 origin.y = 0;
00374 origin.z = 0;
00375
00376 float depth;
00377 bool strip_on = false, flip = false;
00378 const int w=pc->width, h=pc->height;
00379 unsigned char b,g,r;
00380 const int step = ParameterServer::instance()->get<int>("visualization_skip_step");
00381 for( int y = 0; y < h-step; y+=step){
00382 for( int x = 0; x < w-step; x+=step){
00383 using namespace pcl;
00384 if(!strip_on){
00385 const point_type* ll = &pc->points[(x)+(y+step)*w];
00386 if(!validXYZ(*ll)) continue;
00387 const point_type* ur = &pc->points[(x+step)+y*w];
00388 if(!validXYZ(*ur)) continue;
00389
00390 const point_type* ul = &pc->points[x+y*w];
00391 if(validXYZ(*ul)){
00392 depth = squaredEuclideanDistance(*ul,origin);
00393 if (squaredEuclideanDistance(*ul,*ll)/depth <= mesh_thresh and
00394 squaredEuclideanDistance(*ul,*ll)/depth <= mesh_thresh and
00395 squaredEuclideanDistance(*ur,*ll)/depth <= mesh_thresh){
00396 glBegin(GL_TRIANGLE_STRIP);
00397 strip_on = true;
00398 flip = false;
00399
00400
00401 b = *( (unsigned char*)(&ul->rgb));
00402 g = *(1+(unsigned char*)(&ul->rgb));
00403 r = *(2+(unsigned char*)(&ul->rgb));
00404 glColor3ub(r,g,b);
00405
00406
00407 glVertex3f(ul->x, ul->y, ul->z);
00408 }
00409 }
00410 if(!strip_on) {
00411 const point_type* lr = &pc->points[(x+step)+(y+step)*w];
00412 if(!validXYZ(*lr)) {
00413
00414
00415 x++;
00416 continue;
00417 } else {
00418 depth = squaredEuclideanDistance(*ur,origin);
00419 if (squaredEuclideanDistance(*ur,*ll)/depth <= mesh_thresh and
00420 squaredEuclideanDistance(*lr,*ll)/depth <= mesh_thresh and
00421 squaredEuclideanDistance(*ur,*lr)/depth <= mesh_thresh){
00422 glBegin(GL_TRIANGLE_STRIP);
00423 strip_on = true;
00424 flip = true;
00425 }
00426 }
00427 }
00428 if(strip_on) {
00429 b = *( (unsigned char*)(&ll->rgb));
00430 g = *(1+(unsigned char*)(&ll->rgb));
00431 r = *(2+(unsigned char*)(&ll->rgb));
00432 glColor3ub(r,g,b);
00433
00434
00435 glVertex3f(ll->x, ll->y, ll->z);
00436 }
00437 continue;
00438 }
00439 else
00440 {
00441 const point_type* ul;
00442 if(flip){ ul = &pc->points[(x)+(y+step)*w]; }
00443 else { ul = &pc->points[x+y*w]; }
00444 if(validXYZ(*ul)){
00445 depth = squaredEuclideanDistance(*ul,origin);
00446 if (squaredEuclideanDistance(*ul,*(ul-step))/depth > mesh_thresh){
00447 glEnd();
00448 strip_on = false;
00449 continue;
00450 }
00451
00452
00453 b = *( (unsigned char*)(&ul->rgb));
00454 g = *(1+(unsigned char*)(&ul->rgb));
00455 r = *(2+(unsigned char*)(&ul->rgb));
00456 glColor3ub(r,g,b);
00457
00458
00459 glVertex3f(ul->x, ul->y, ul->z);
00460 } else {
00461 glEnd();
00462 strip_on = false;
00463 continue;
00464 }
00465
00466 const point_type* ll;
00467 if(flip){ ll = &pc->points[x+y*w]; }
00468 else { ll = &pc->points[(x)+(y+step)*w]; }
00469 if(validXYZ(*ll)){
00470 depth = squaredEuclideanDistance(*ll,origin);
00471 if (squaredEuclideanDistance(*ul,*ll)/depth > mesh_thresh or
00472 squaredEuclideanDistance(*ul,*(ul-step))/depth > mesh_thresh or
00473 squaredEuclideanDistance(*ll,*(ll-step))/depth > mesh_thresh){
00474 glEnd();
00475 strip_on = false;
00476 continue;
00477 }
00478 b = *( (unsigned char*)(&ll->rgb));
00479 g = *(1+(unsigned char*)(&ll->rgb));
00480 r = *(2+(unsigned char*)(&ll->rgb));
00481 glColor3ub(r,g,b);
00482
00483 glVertex3f(ll->x, ll->y, ll->z);
00484 } else {
00485 glEnd();
00486 strip_on = false;
00487 continue;
00488 }
00489 }
00490 }
00491 if(strip_on) glEnd();
00492 strip_on = false;
00493 }
00494 ROS_DEBUG("Compiled pointcloud into list %i", cloud_list_index);
00495 glEndList();
00496
00497
00498
00499
00500 Q_EMIT cloudRendered(pc);
00501 clock_gettime(CLOCK_MONOTONIC, &finish); elapsed = (finish.tv_sec - starttime.tv_sec); elapsed += (finish.tv_nsec - starttime.tv_nsec) / 1000000000.0; ROS_INFO_STREAM_COND_NAMED(elapsed > ParameterServer::instance()->get<double>("min_time_reported"), "timings", __FUNCTION__ << " runtime: "<< elapsed <<" s");
00502 }
00503
00504 void GLViewer::deleteLastNode(){
00505 if(cloud_list_indices.size() <= 1){
00506 this->reset();
00507 return;
00508 }
00509 GLuint nodeId = cloud_list_indices.back();
00510 cloud_list_indices.pop_back();
00511 glDeleteLists(nodeId,1);
00512 }
00513
00514 void GLViewer::pointCloud2GLList(pointcloud_type const * pc){
00515 struct timespec starttime, finish; double elapsed; clock_gettime(CLOCK_MONOTONIC, &starttime);
00516 ROS_DEBUG("Making GL list from point-cloud pointer %p in thread %d", pc, (unsigned int)QThread::currentThreadId());
00517 GLuint cloud_list_index = glGenLists(1);
00518 if(!cloud_list_index) {
00519 ROS_ERROR("No display list could be created");
00520 return;
00521 }
00522 float mesh_thresh = ParameterServer::instance()->get<double>("squared_meshing_threshold");
00523 cloud_list_indices.push_back(cloud_list_index);
00524 glNewList(cloud_list_index, GL_COMPILE);
00525 glBegin(GL_TRIANGLES);
00526
00527 point_type origin;
00528 origin.x = 0;
00529 origin.y = 0;
00530 origin.z = 0;
00531
00532 float depth;
00533 unsigned int w=pc->width, h=pc->height;
00534 for(unsigned int x = 0; x < w-1; x++){
00535 for(unsigned int y = 0; y < h-1; y++){
00536 using namespace pcl;
00537
00538 const point_type* pi = &pc->points[x+y*w];
00539
00540 if(!(validXYZ(*pi))) continue;
00541 depth = squaredEuclideanDistance(*pi,origin);
00542
00543 const point_type* pl = &pc->points[(x+1)+(y+1)*w];
00544 if(!(validXYZ(*pl)) or squaredEuclideanDistance(*pi,*pl)/depth > mesh_thresh)
00545 continue;
00546
00547 const point_type* pj = &pc->points[(x+1)+y*w];
00548 if(validXYZ(*pj)
00549 and squaredEuclideanDistance(*pi,*pj)/depth <= mesh_thresh
00550 and squaredEuclideanDistance(*pj,*pl)/depth <= mesh_thresh){
00551 drawTriangle(*pi, *pj, *pl);
00552 }
00553 const point_type* pk = &pc->points[(x)+(y+1)*w];
00554
00555 if(validXYZ(*pk)
00556 and squaredEuclideanDistance(*pi,*pk)/depth <= mesh_thresh
00557 and squaredEuclideanDistance(*pk,*pl)/depth <= mesh_thresh){
00558 drawTriangle(*pi, *pk, *pl);
00559 }
00560 }
00561 }
00562 glEnd();
00563 ROS_DEBUG("Compiled pointcloud into list %i", cloud_list_index);
00564 glEndList();
00565 clock_gettime(CLOCK_MONOTONIC, &finish); elapsed = (finish.tv_sec - starttime.tv_sec); elapsed += (finish.tv_nsec - starttime.tv_nsec) / 1000000000.0; ROS_INFO_STREAM_COND_NAMED(elapsed > ParameterServer::instance()->get<double>("min_time_reported"), "timings", __FUNCTION__ << " runtime: "<< elapsed <<" s");
00566 }
00567
00568 void GLViewer::reset(){
00569 glDeleteLists(1,cloud_list_indices.back());
00570 cloud_list_indices.clear();
00571 cloud_matrices->clear();
00572 if(edge_list_) {
00573 delete edge_list_;
00574 edge_list_ = NULL;
00575 }
00576 updateGL();
00577 }
00578 QImage GLViewer::renderList(QMatrix4x4 transform, int list_id){
00579 return QImage();
00580 }
00581
00582 void GLViewer::setEdges(QList<QPair<int, int> >* edge_list){
00583 if(edge_list_) delete edge_list_;
00584 edge_list_ = edge_list;
00585 }
00586
00587 void GLViewer::drawEdges(){
00588 if(edge_list_ == NULL) return;
00589 glBegin(GL_LINES);
00590 glLineWidth(12);
00591 for(int i = 0; i < edge_list_->size(); i++){
00592 int id1 = (*edge_list_)[i].first;
00593 int id2 = (*edge_list_)[i].second;
00594 float x,y,z;
00595 if(cloud_matrices->size() > id1 && cloud_matrices->size() > id2){
00596 if(abs(id1 - id2) == 1){
00597 glColor4f(bg_col_[0],1-bg_col_[1],1-bg_col_[2],1.0);
00598 } else if(abs(id1 - id2) > 20){
00599 glColor4f(1-bg_col_[0],1-bg_col_[1],bg_col_[2],0.4);
00600 } else {
00601 glColor4f(1-bg_col_[0],1-bg_col_[1],1-bg_col_[2],0.4);
00602 }
00603 x = (*cloud_matrices)[id1](0,3);
00604 y = (*cloud_matrices)[id1](1,3);
00605 z = (*cloud_matrices)[id1](2,3);
00606 glVertex3f(x,y,z);
00607 x = (*cloud_matrices)[id2](0,3);
00608 y = (*cloud_matrices)[id2](1,3);
00609 z = (*cloud_matrices)[id2](2,3);
00610 glVertex3f(x,y,z);
00611 }
00612 else ROS_ERROR("Not enough cloud matrices (%d) for vertex ids (%d and %d)", cloud_matrices->size(), id1, id2);
00613 }
00614 glEnd();
00615 }
00616
00617
00618 void GLViewer::setViewPoint(QMatrix4x4 new_vp){
00620 viewpoint_tf_ = new_vp.inverted();
00621 }
00622
00623 bool GLViewer::setClickedPosition(int x, int y) {
00624 GLint viewport[4];
00625 GLdouble modelview[16];
00626 GLdouble projection[16];
00627 GLfloat winX, winY, winZ;
00628 GLdouble posX, posY, posZ;
00629
00630 glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
00631 glGetDoublev( GL_PROJECTION_MATRIX, projection );
00632 glGetIntegerv( GL_VIEWPORT, viewport );
00633
00634 winX = (float)x;
00635 winY = (float)viewport[3] - (float)y;
00636 glReadPixels( x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
00637 if(winZ != 1){
00638 gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
00639 ROS_INFO_STREAM((float)winZ << ", " << posX << "," << posY << "," << posZ);
00640 viewpoint_tf_(0,3) = -posX;
00641 viewpoint_tf_(1,3) = -posY;
00642 viewpoint_tf_(2,3) = -posZ;
00643 return true;
00644 } else {
00645 return false;
00646 }
00647 }
00648
00649 void GLViewer::toggleTriangulation() {
00650 ROS_INFO("Toggling Triangulation");
00651 if(polygon_mode == GL_FILL){
00652 polygon_mode = GL_POINT;
00653 } else if(polygon_mode == GL_POINT){
00654 polygon_mode = GL_LINE;
00655 } else {
00656 polygon_mode = GL_FILL;
00657 }
00658 glPolygonMode(GL_FRONT_AND_BACK, polygon_mode);
00659 updateGL();
00660 }
00661
00662 void GLViewer::drawToPS(QString filname){
00663 #ifdef GL2PS
00664
00665 FILE *fp = fopen("glviewer.pdf", "wb");
00666 GLint buffsize = 0, state = GL2PS_OVERFLOW;
00667 GLint viewport[4];
00668 char *oldlocale = setlocale(LC_NUMERIC, "C");
00669
00670
00671 glGetIntegerv(GL_VIEWPORT, viewport);
00672
00673 while( state == GL2PS_OVERFLOW ){
00674 buffsize += 1024*1024;
00675 gl2psBeginPage ( "GL View", "RGBD-SLAM", viewport,
00676 GL2PS_PDF, GL2PS_BSP_SORT, GL2PS_SILENT |
00677 GL2PS_SIMPLE_LINE_OFFSET | GL2PS_NO_BLENDING |
00678 GL2PS_OCCLUSION_CULL | GL2PS_BEST_ROOT,
00679 GL_RGBA, 0, NULL, 0, 0, 0, buffsize,
00680 fp, "LatexFile" );
00681 drawClouds(0.0);
00682 state = gl2psEndPage();
00683 }
00684 setlocale(LC_NUMERIC, oldlocale);
00685 fclose(fp);
00686 #else
00687 QMessageBox::warning(this, tr("This functionality is not supported."), tr("This feature needs to be compiled in. To do so, install libgl2ps-dev and set the USE_GL2PS flag at the top of CMakeLists.txt. The feature has been removed to ease the installation process, sorry for the inconvenience."));
00688 #endif
00689 }