00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef DUMMYGLVIEWER
00019
00020 #include "ros/ros.h"
00021 #include <QtGui>
00022 #include <QtOpenGL>
00023 #include <QThread>
00024 #include <GL/glut.h>
00025 #include "boost/foreach.hpp"
00026 #include <cmath>
00027 #include <QApplication>
00028 #include <QAction>
00029 #include <QMenu>
00030 #ifdef GL2PS
00031 #include <gl2ps.h>
00032 #endif
00033 #include "glviewer.h"
00034 #include "misc2.h"
00035 #include "scoped_timer.h"
00036
00037 #ifndef GL_MULTISAMPLE
00038 #define GL_MULTISAMPLE 0x809D
00039 #endif
00040
00041 const double PI= 3.14159265358979323846;
00042
00043 template <typename PointType>
00044 inline bool validXYZ(const PointType& p, float max_depth){
00045 if(max_depth < p.z) return false;
00046 return std::isfinite(p.z) && std::isfinite(p.y) && std::isfinite(p.x);
00047 };
00048
00049 template <typename PointType>
00050 inline void setGLColor(const PointType& p){
00051 static int previous_segment = -1;
00052 unsigned char b,g,r;
00053 #ifdef RGB_IS_4TH_DIM
00054 b = *( (unsigned char*)(&p.data[3]));
00055 g = *(1+(unsigned char*)(&p.data[3]));
00056 r = *(2+(unsigned char*)(&p.data[3]));
00057 #elif defined(HEMACLOUDS)
00058 if(p.segment == 0 || ParameterServer::instance()->get<int>("segment_to_optimize") < 0) {
00059 b = *( (unsigned char*)(&p.rgb));
00060 g = *(1+(unsigned char*)(&p.rgb));
00061 r = *(2+(unsigned char*)(&p.rgb));
00062 } else if(ParameterServer::instance()->get<int>("segment_to_optimize") != 0) {
00063 if(p.segment == ParameterServer::instance()->get<int>("segment_to_optimize")) {
00064 r = 0; g = 255; b = 0;
00065 } else {
00066 r = 255; g = 0; b = 0;
00067 }
00068 } else {
00069 switch(p.segment & 15){
00070 case 0 : r = 0; g = 0; b = 0; ROS_INFO_COND(p.segment != previous_segment, "%d is black ", p.segment); break;
00071 case 1 : r = 128; g = 128; b = 0; ROS_INFO_COND(p.segment != previous_segment, "%d is yellow ", p.segment); break;
00072 case 2 : r = 128; g = 0; b = 0; ROS_INFO_COND(p.segment != previous_segment, "%d is red ", p.segment); break;
00073 case 3 : r = 128; g = 0; b = 128; ROS_INFO_COND(p.segment != previous_segment, "%d is magenta ", p.segment); break;
00074 case 4 : r = 0; g = 128; b = 128; ROS_INFO_COND(p.segment != previous_segment, "%d is cyan ", p.segment); break;
00075 case 5 : r = 0; g = 128; b = 0; ROS_INFO_COND(p.segment != previous_segment, "%d is green ", p.segment); break;
00076 case 6 : r = 0; g = 0; b = 128; ROS_INFO_COND(p.segment != previous_segment, "%d is blue ", p.segment); break;
00077 case 7 : r = 255; g = 255; b = 255; ROS_INFO_COND(p.segment != previous_segment, "%d is white ", p.segment); break;
00078 case 8 : r = 128; g = 128; b = 128; ROS_INFO_COND(p.segment != previous_segment, "%d is gray ", p.segment); break;
00079 case 9 : r = 255; g = 255; b = 128; ROS_INFO_COND(p.segment != previous_segment, "%d is yellowish ", p.segment); break;
00080 case 10: r = 255; g = 128; b = 128; ROS_INFO_COND(p.segment != previous_segment, "%d is redish ", p.segment); break;
00081 case 11: r = 255; g = 128; b = 255; ROS_INFO_COND(p.segment != previous_segment, "%d is magentaish ", p.segment); break;
00082 case 12: r = 128; g = 255; b = 255; ROS_INFO_COND(p.segment != previous_segment, "%d is cyanish ", p.segment); break;
00083 case 13: r = 128; g = 255; b = 128; ROS_INFO_COND(p.segment != previous_segment, "%d is greenish ", p.segment); break;
00084 case 14: r = 128; g = 128; b = 255; ROS_INFO_COND(p.segment != previous_segment, "%d is blueish ", p.segment); break;
00085 case 15: r = 255; g = 255; b = 255; ROS_INFO_COND(p.segment != previous_segment, "%d is white ", p.segment); break;
00086 default: ROS_ERROR("Impossible value %d", p.segment % 8);
00087 }
00088 previous_segment = p.segment;
00089 }
00090 #else
00091 b = *( (unsigned char*)(&p.rgb));
00092 g = *(1+(unsigned char*)(&p.rgb));
00093 r = *(2+(unsigned char*)(&p.rgb));
00094 #endif
00095 glColor3ub(r,g,b);
00096 };
00097
00098 GLViewer::GLViewer(QWidget *parent)
00099 : QGLWidget(QGLFormat(QGL::NoSampleBuffers), parent),
00100
00101 polygon_mode(GL_FILL),
00102 cloud_list_indices(),
00103 cloud_matrices(new QList<QMatrix4x4>()),
00104 show_poses_(ParameterServer::instance()->get<bool>("show_axis")),
00105 show_ids_(false),
00106 show_grid_(false),
00107 show_tfs_(false),
00108 show_edges_(ParameterServer::instance()->get<bool>("show_axis")),
00109 show_clouds_(true),
00110 show_octomap_(true),
00111 show_features_(false),
00112 follow_mode_(true),
00113 stereo_(false),
00114 black_background_(true),
00115 width_(0),
00116 height_(0),
00117 stereo_shift_(0.1),
00118 fov_(100.0/180.0*PI),
00119 rotation_stepping_(1.0),
00120 myparent(parent),
00121 button_pressed_(false),
00122 non_interactive_update_(false),
00123 fast_rendering_step_(1),
00124 external_renderable(NULL)
00125 {
00126 this->initialPosition();
00127 this->format().setSwapInterval(0);
00128 bg_col_[0] = bg_col_[1] = bg_col_[2] = bg_col_[3] = 0.01;
00129 ROS_DEBUG_COND(!this->format().stereo(), "Stereo not supported");
00130 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00131 viewpoint_tf_.setToIdentity();
00132 this->renderText(0,0,0, "RGBDSLAMv2", QFont("Monospace", 14));
00133 }
00134
00135 GLViewer::~GLViewer() { }
00136
00137 void GLViewer::initialPosition() {
00138 xRot = 180*16.0;
00139 yRot = 0;
00140 zRot = 0;
00141 xTra = 0;
00142 yTra = 0;
00143 zTra = -50;
00144 }
00145
00146 QSize GLViewer::minimumSizeHint() const {
00147 return QSize(400, 400);
00148 }
00149
00150 QSize GLViewer::sizeHint() const {
00151 return QSize(640, 480);
00152 }
00153
00154 static void qNormalizeAngle(int &angle) {
00155 while (angle < 0)
00156 angle += 360 * 16;
00157 while (angle > 360 * 16)
00158 angle -= 360 * 16;
00159 }
00160
00161 void GLViewer::setXRotation(int angle) {
00162 qNormalizeAngle(angle);
00163 if (angle != xRot) {
00164 xRot = angle;
00165
00166 }
00167 }
00168
00169
00170 void GLViewer::setYRotation(int angle) {
00171 qNormalizeAngle(angle);
00172 if (angle != yRot) {
00173 yRot = angle;
00174
00175 }
00176 }
00177
00178 void GLViewer::setZRotation(int angle) {
00179 qNormalizeAngle(angle);
00180 if (angle != zRot) {
00181 zRot = angle;
00182
00183 }
00184 }
00185
00186 void GLViewer::setRotationGrid(double rot_step_in_degree) {
00187 rotation_stepping_ = rot_step_in_degree;
00188 }
00189
00190 void GLViewer::setStereoShift(double shift) {
00191 stereo_shift_ = shift;
00192 clearAndUpdate();
00193 }
00194
00195 void GLViewer::initializeGL() {
00196 glClearColor(bg_col_[0],bg_col_[1],bg_col_[2],bg_col_[3]);
00197 glEnable (GL_BLEND);
00198 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00199 glEnable(GL_DEPTH_TEST);
00200 glEnable(GL_CULL_FACE);
00201 glEnable(GL_LINE_SMOOTH);
00202
00203
00204 glDisable(GL_LIGHTING);
00205
00206
00207
00209
00210
00211 }
00212
00213 inline
00214 void GLViewer::drawTriangle(const point_type& p1, const point_type& p2, const point_type& p3){
00215 setGLColor(p1);
00216 glVertex3f(p1.x, p1.y, p1.z);
00217
00218 setGLColor(p2);
00219 glVertex3f(p2.x, p2.y, p2.z);
00220
00221 setGLColor(p3);
00222 glVertex3f(p3.x, p3.y, p3.z);
00223 }
00224
00225 void GLViewer::drawGrid(){
00226
00227
00228
00229 glBegin(GL_LINES);
00230 glLineWidth(1);
00231 ParameterServer* ps = ParameterServer::instance();
00232 float scale = ps->get<double>("gl_cell_size");
00233
00234 glColor3f(0.5,0.5,0.5);
00235 int size = ps->get<int>("gl_grid_size_xy")/2;
00236 for(int i = -size; i <= size ; i++){
00237
00238 glVertex3f(i*scale, size*scale, 0);
00239 glVertex3f(i*scale, -size*scale, 0);
00240
00241 glVertex3f( size*scale, i*scale, 0);
00242 glVertex3f(-size*scale, i*scale, 0);
00243 }
00244 size = ps->get<int>("gl_grid_size_xz")/2;
00245 for(int i = -size; i <= size ; i++){
00246
00247 glVertex3f(i*scale, 0, size*scale);
00248 glVertex3f(i*scale, 0, -size*scale);
00249
00250 glVertex3f( size*scale, 0, i*scale);
00251 glVertex3f(-size*scale, 0, i*scale);
00252 }
00253 size = ps->get<int>("gl_grid_size_yz")/2;
00254 for(int i = -size; i <= size ; i++){
00255
00256 glVertex3f(0, i*scale, size*scale);
00257 glVertex3f(0, i*scale, -size*scale);
00258
00259 glVertex3f(0, size*scale, i*scale);
00260 glVertex3f(0, -size*scale, i*scale);
00261 }
00262 glEnd();
00263
00264 }
00265
00266 void GLViewer::drawAxes(float scale, float thickness){
00267 glEnable(GL_BLEND);
00268 glBegin(GL_LINES);
00269 glLineWidth(thickness);
00270 glColor4f (0.9, 0, 0, 1.0);
00271 glVertex3f(0, 0, 0);
00272 glColor4f (0.9, 0, 0, 0.0);
00273 glVertex3f(scale, 0, 0);
00274 glColor4f (0, 0.9, 0, 1.0);
00275 glVertex3f(0, 0, 0);
00276 glColor4f (0, 0.9, 0, 0.0);
00277 glVertex3f(0, scale, 0);
00278 glColor4f (0, 0, 0.9, 1.0);
00279 glVertex3f(0, 0, 0);
00280 glColor4f (0, 0, 0.9, 0.0);
00281 glVertex3f(0, 0, scale);
00282 glEnd();
00283 }
00284 void GLViewer::makeCurrent(){
00285 ScopedTimer s(__FUNCTION__);
00286 if(context() != context()->currentContext()){
00287 ScopedTimer s("QGLWidget::makeCurrent");
00288 QGLWidget::makeCurrent();
00289 }
00290 }
00291 void GLViewer::paintGL() {
00292 if(!this->isVisible()) return;
00293 ScopedTimer s(__FUNCTION__);
00294
00295 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00296 glPointSize(ParameterServer::instance()->get<double>("gl_point_size"));
00297 if(stereo_){
00298 this->format().setStereo(true);
00299 float ratio = (float)(width_) / (float) height_;
00300 glViewport(0, 0, width_/2, height_);
00301 glMatrixMode(GL_PROJECTION);
00302 glLoadIdentity();
00303 gluPerspective(fov_, ratio, 0.1, 1e4);
00304 glMatrixMode(GL_MODELVIEW);
00305 drawClouds(stereo_shift_);
00306
00307 glViewport(width_/2, 0, width_/2, height_);
00308 glMatrixMode(GL_PROJECTION);
00309 glLoadIdentity();
00310 gluPerspective(fov_, ratio, 0.1, 1e4);
00311 glMatrixMode(GL_MODELVIEW);
00312 }
00313 if(cloud_matrices->size() == 0){
00314 glColor4f(1,0,0,1);
00315 this->renderText(-0.36,0.1,1, QString("R"), QFont("Serif", 28, QFont::Bold, false));
00316 glColor4f(0,1,0,1);
00317 this->renderText(-0.27,0.1,1, QString("G"), QFont("Serif", 28, QFont::Bold, false));
00318 glColor4f(0,0,1,1);
00319 this->renderText(-0.18,0.1,1, QString("B"), QFont("Serif", 28, QFont::Bold, false));
00320 glColor4f(.5,.5,.5,1);
00321 this->renderText(-0.09,0.1,1, QString("D"), QFont("Serif", 28, QFont::Bold, false));
00322 glColor4f(1-bg_col_[0],1-bg_col_[1],1-bg_col_[2],1.0);
00323 this->renderText(0.01,0.1,1, QString("S"), QFont("Sans", 28, -1,false));
00324 this->renderText(0.08,0.1,1, QString("L"), QFont("Sans", 28, -1,false));
00325 this->renderText(0.15,0.1,1, QString("A"), QFont("Sans", 28, -1,false));
00326 this->renderText(0.23,0.1,1, QString("M"), QFont("Sans", 28, -1,false));
00327 glColor4f(1-bg_col_[0],1-bg_col_[1],1-bg_col_[2],0.2);
00328 this->renderText(0.33,0.1,1, QString("v2"), QFont("Sans", 28, -1, true));
00329 }
00330 drawClouds(0.0);
00331 drawRenderable();
00332 }
00333
00334 void GLViewer::drawRenderable() {
00335 if(show_octomap_ && external_renderable != NULL){
00336 external_renderable->render();
00337 }
00338 }
00339 void GLViewer::drawOneCloud(int i) {
00340 glPushMatrix();
00341 glMultMatrixd(static_cast<GLdouble*>( (*cloud_matrices)[i].data() ));
00342 if(show_clouds_) glCallList(cloud_list_indices[i]);
00343 if(show_features_ && feature_list_indices.size()>i){
00344 glCallList(feature_list_indices[i]);
00345 }
00346 glPopMatrix();
00347 }
00348 void GLViewer::drawClouds(float xshift) {
00349 ScopedTimer s(__FUNCTION__);
00350 ParameterServer* ps = ParameterServer::instance();
00351 if(follow_mode_){
00352 int id = cloud_matrices->size()-1;
00353 if(id >= 0)setViewPoint((*cloud_matrices)[id]);
00354 }
00355 glDisable (GL_BLEND);
00356 glLoadIdentity();
00357
00358 glTranslatef(xTra+xshift, yTra, zTra);
00359 if(button_pressed_){
00360 drawNavigationAxis(0, 0.5, "mouse up/down");
00361 }
00362 int x_steps = (xRot / 16.0)/rotation_stepping_;
00363 glRotatef(x_steps*rotation_stepping_, 1.0, 0.0, 0.0);
00364
00365 if(button_pressed_){
00366 drawNavigationAxis(1, 0.5, "mouse left/right");
00367 }
00368 int y_steps = (yRot / 16.0)/rotation_stepping_;
00369 glRotatef(y_steps*rotation_stepping_, 0.0, 1.0, 0.0);
00370
00371 int z_steps = (zRot / 16.0)/rotation_stepping_;
00372 glRotatef(z_steps*rotation_stepping_, 0.0, 0.0, 1.0);
00373 if(button_pressed_){
00374 drawNavigationAxis(2, 0.5, "ctrl + left/right");
00375 }
00376
00377 glMultMatrixd(static_cast<GLdouble*>( viewpoint_tf_.data() ));
00378 if(show_grid_) {
00379 drawGrid();
00380 }
00381 if(show_poses_) drawAxes(0.5);
00382
00383 ROS_DEBUG("Drawing %i PointClouds", cloud_list_indices.size());
00384 int step = 1;
00385 if(button_pressed_ || non_interactive_update_){
00386 step = std::max(step,(int)fast_rendering_step_);
00387 step = std::max(step,ps->get<int>("fast_rendering_step"));
00388 }
00389 int last_cloud = std::min(cloud_list_indices.size(), cloud_matrices->size());
00390 int first_cloud = 0;
00391
00392
00393 int specific_cloud = ps->get<int>("show_cloud_with_id");
00394 if(specific_cloud >= 0){
00395 drawOneCloud(specific_cloud);
00396 }
00397 else
00398 {
00399 int i = 0;
00400 for(; i < last_cloud - 10; i+=step){
00401 ROS_DEBUG("Drawing %d. PointCloud", i);
00402 drawOneCloud(i);
00403 }
00404 for(int j = std::max(last_cloud - 10, 0); j < last_cloud; j++){
00405 ROS_DEBUG("Drawing %d. PointCloud.", j);
00406 drawOneCloud(j);
00407 }
00408
00409 }
00410
00411 glDisable(GL_DEPTH_TEST);
00412 if(show_edges_) drawEdges();
00413
00414 for(int i = 0; i<cloud_list_indices.size() && i<cloud_matrices->size(); i++){
00415 glPushMatrix();
00416 glMultMatrixd(static_cast<GLdouble*>( (*cloud_matrices)[i].data() ));
00417 if(show_poses_) drawAxes((i + 1 == cloud_list_indices.size()) ? 0.5:0.075);
00418 if(show_ids_) {
00419 glColor4f(1-bg_col_[0],1-bg_col_[1],1-bg_col_[2],1.0);
00420 this->renderText(0.,0.,0.,QString::number(i), QFont("Monospace", 8));
00421 }
00422 glPopMatrix();
00423 }
00424 glEnable(GL_DEPTH_TEST);
00425 }
00426
00427 void GLViewer::resizeGL(int width, int height)
00428 {
00429 width_ = width;
00430 height_ = height;
00431
00432 glViewport(0, 0, width, height);
00433
00434
00435 glMatrixMode(GL_PROJECTION);
00436 glLoadIdentity();
00437
00438
00439
00440
00441
00442
00443 float ratio = (float)width / (float) height;
00444 gluPerspective(fov_, ratio, 0.1, 1e4);
00445 glMatrixMode(GL_MODELVIEW);
00446 }
00447
00448 void GLViewer::mouseDoubleClickEvent(QMouseEvent *event) {
00449
00450 this->initialPosition();
00451 if(cloud_matrices->size()>0){
00452 int id = 0;
00453 switch (QApplication::keyboardModifiers()){
00454 case Qt::NoModifier:
00455 id = cloud_matrices->size()-1;
00456 follow_mode_ = true;
00457 setViewPoint((*cloud_matrices)[id]);
00458 break;
00459 case Qt::ControlModifier:
00460 follow_mode_ = false;
00461 setViewPoint((*cloud_matrices)[id]);
00462 break;
00463 case Qt::ShiftModifier:
00464 viewpoint_tf_.setToIdentity();
00465 }
00466 }
00467 if(setClickedPosition(event->x(), event->y())){
00468
00469 follow_mode_ = false;
00470 }
00471 clearAndUpdate();
00472 }
00473 void GLViewer::toggleStereo(bool flag){
00474 stereo_ = flag;
00475 resizeGL(width_, height_);
00476 clearAndUpdate();
00477 }
00478 void GLViewer::toggleBackgroundColor(bool flag){
00479 black_background_ = flag;
00480 if(flag){
00481 bg_col_[0] = bg_col_[1] = bg_col_[2] = bg_col_[3] = 0.01;
00482 }
00483 else{
00484 bg_col_[0] = bg_col_[1] = bg_col_[2] = 1.0;
00485 }
00486 glClearColor(bg_col_[0],bg_col_[1],bg_col_[2],bg_col_[3]);
00487 clearAndUpdate();
00488 }
00489 void GLViewer::toggleShowFeatures(bool flag){
00490 show_features_ = flag;
00491 clearAndUpdate();
00492 }
00493 void GLViewer::toggleShowOctoMap(bool flag){
00494 show_octomap_ = flag;
00495 clearAndUpdate();
00496 }
00497 void GLViewer::toggleShowClouds(bool flag){
00498 show_clouds_ = flag;
00499 clearAndUpdate();
00500 }
00501 void GLViewer::toggleShowTFs(bool flag){
00502 show_tfs_ = flag;
00503 clearAndUpdate();
00504 }
00505 void GLViewer::toggleShowGrid(bool flag){
00506 show_grid_ = flag;
00507 clearAndUpdate();
00508 }
00509 void GLViewer::toggleShowIDs(bool flag){
00510 show_ids_ = flag;
00511 clearAndUpdate();
00512 }
00513 void GLViewer::toggleShowEdges(bool flag){
00514 show_edges_ = flag;
00515 clearAndUpdate();
00516 }
00517 void GLViewer::toggleShowPoses(bool flag){
00518 show_poses_ = flag;
00519 clearAndUpdate();
00520 }
00521 void GLViewer::toggleFollowMode(bool flag){
00522 follow_mode_ = flag;
00523 }
00524
00526 void GLViewer::mouseReleaseEvent(QMouseEvent *event) {
00527 button_pressed_ = false;
00528 clearAndUpdate();
00529
00530 if(event->button() == Qt::RightButton)
00531 {
00532 QMenu menu;
00533 QMenu* viewMenu = &menu;
00534 GLViewer* glviewer = this;
00535
00536 QAction *toggleCloudDisplay = new QAction(tr("Show &Clouds"), this);
00537 toggleCloudDisplay->setCheckable(true);
00538 toggleCloudDisplay->setChecked(show_clouds_);
00539 toggleCloudDisplay->setStatusTip(tr("Toggle whether point clouds should be rendered"));
00540 connect(toggleCloudDisplay, SIGNAL(toggled(bool)), glviewer, SLOT(toggleShowClouds(bool)));
00541 viewMenu->addAction(toggleCloudDisplay);
00542
00543 QAction *toggleOctoMapDisplay = new QAction(tr("Show &Octomap"), this);
00544 toggleOctoMapDisplay->setShortcut(QString("O"));
00545 toggleOctoMapDisplay->setCheckable(true);
00546 toggleOctoMapDisplay->setChecked(show_octomap_);
00547 toggleOctoMapDisplay->setStatusTip(tr("Toggle whether octomap should be displayed"));
00548 connect(toggleOctoMapDisplay, SIGNAL(toggled(bool)), glviewer, SLOT(toggleShowOctoMap(bool)));
00549 viewMenu->addAction(toggleOctoMapDisplay);
00550
00551 QAction *toggleShowPosesAct = new QAction(tr("Show &Poses of Graph"), this);
00552 toggleShowPosesAct->setShortcut(QString("P"));
00553 toggleShowPosesAct->setCheckable(true);
00554 toggleShowPosesAct->setChecked(show_poses_);
00555 toggleShowPosesAct->setStatusTip(tr("Display poses as axes"));
00556 connect(toggleShowPosesAct, SIGNAL(toggled(bool)), glviewer, SLOT(toggleShowPoses(bool)));
00557 viewMenu->addAction(toggleShowPosesAct);
00558
00559 QAction *toggleShowIDsAct = new QAction(tr("Show Pose IDs"), this);
00560 toggleShowIDsAct->setShortcut(QString("I"));
00561 toggleShowIDsAct->setCheckable(true);
00562 toggleShowIDsAct->setChecked(show_ids_);
00563 toggleShowIDsAct->setStatusTip(tr("Display pose ids at axes"));
00564 connect(toggleShowIDsAct, SIGNAL(toggled(bool)), glviewer, SLOT(toggleShowIDs(bool)));
00565 viewMenu->addAction(toggleShowIDsAct);
00566
00567 QAction *toggleShowEdgesAct = new QAction(tr("Show &Edges of Graph"), this);
00568 toggleShowEdgesAct->setShortcut(QString("E"));
00569 toggleShowEdgesAct->setCheckable(true);
00570 toggleShowEdgesAct->setChecked(show_edges_);
00571 toggleShowEdgesAct->setStatusTip(tr("Display edges of pose graph as lines"));
00572 connect(toggleShowEdgesAct, SIGNAL(toggled(bool)), glviewer, SLOT(toggleShowEdges(bool)));
00573 viewMenu->addAction(toggleShowEdgesAct);
00574
00575 QAction *toggleShowTFs = new QAction(tr("Show Pose TFs"), this);
00576 toggleShowTFs->setCheckable(true);
00577 toggleShowTFs->setChecked(show_tfs_);
00578 toggleShowTFs->setStatusTip(tr("Display pose transformations at axes"));
00579 connect(toggleShowTFs, SIGNAL(toggled(bool)), glviewer, SLOT(toggleShowTFs(bool)));
00580 viewMenu->addAction(toggleShowTFs);
00581
00582 QAction *toggleShowFeatures = new QAction(tr("Show &Feature Locations"), this);
00583 toggleShowFeatures->setCheckable(true);
00584 toggleShowFeatures->setChecked(show_features_);
00585 toggleShowFeatures->setStatusTip(tr("Toggle whether feature locations should be rendered"));
00586 connect(toggleShowFeatures, SIGNAL(toggled(bool)), glviewer, SLOT(toggleShowFeatures(bool)));
00587 viewMenu->addAction(toggleShowFeatures);
00588
00589 QAction *toggleTriangulationAct = new QAction(tr("&Toggle Triangulation"), this);
00590 toggleTriangulationAct->setShortcut(QString("T"));
00591 toggleTriangulationAct->setStatusTip(tr("Switch between surface, wireframe and point cloud"));
00592 connect(toggleTriangulationAct, SIGNAL(triggered(bool)), glviewer, SLOT(toggleTriangulation()));
00593 viewMenu->addAction(toggleTriangulationAct);
00594
00595 QAction *toggleFollowAct = new QAction(tr("Follow &Camera"), this);
00596 toggleFollowAct->setShortcut(QString("Shift+F"));
00597 toggleFollowAct->setCheckable(true);
00598 toggleFollowAct->setChecked(follow_mode_);
00599 toggleFollowAct->setStatusTip(tr("Always use viewpoint of last frame (except zoom)"));
00600 connect(toggleFollowAct, SIGNAL(toggled(bool)), glviewer, SLOT(toggleFollowMode(bool)));
00601 viewMenu->addAction(toggleFollowAct);
00602
00603 QAction *toggleShowGrid = new QAction(tr("Show Grid"), this);
00604 toggleShowGrid->setCheckable(true);
00605 toggleShowGrid->setChecked(show_grid_);
00606 toggleShowGrid->setStatusTip(tr("Display XY plane grid"));
00607 connect(toggleShowGrid, SIGNAL(toggled(bool)), glviewer, SLOT(toggleShowGrid(bool)));
00608 viewMenu->addAction(toggleShowGrid);
00609
00610 QAction *toggleBGColor = new QAction(tr("Toggle Background"), this);
00611 toggleBGColor->setShortcut(QString("B"));
00612 toggleBGColor->setCheckable(true);
00613 toggleBGColor->setChecked(black_background_);
00614 toggleBGColor->setStatusTip(tr("Toggle whether background should be white or black"));
00615 connect(toggleBGColor, SIGNAL(toggled(bool)), glviewer, SLOT(toggleBackgroundColor(bool)));
00616 viewMenu->addAction(toggleBGColor);
00617
00618 viewMenu->exec(mapToGlobal(event->pos()));
00619 }
00620 QGLWidget::mouseReleaseEvent(event);
00621 }
00622
00623 void GLViewer::mousePressEvent(QMouseEvent *event) {
00624 button_pressed_ = true;
00625 lastPos = event->pos();
00626 }
00627
00628 void GLViewer::wheelEvent(QWheelEvent *event) {
00629 double size;
00630 switch (QApplication::keyboardModifiers()){
00631 case Qt::ControlModifier:
00632 size = ParameterServer::instance()->get<double>("gl_point_size");
00633
00634
00635
00636
00637
00638
00639
00640
00641 size = std::max(1.0, size + event->delta()/120.0);
00642 ParameterServer::instance()->set<double>("gl_point_size", size);
00643 break;
00644 case Qt::ShiftModifier:
00645 case Qt::NoModifier:
00646 default:
00647 zTra += (-zTra/50.0)*((float)event->delta())/25.0;
00648 }
00649 clearAndUpdate();
00650 }
00651 void GLViewer::mouseMoveEvent(QMouseEvent *event) {
00652 int dx = event->x() - lastPos.x();
00653 int dy = event->y() - lastPos.y();
00654
00655 if (event->buttons() & Qt::LeftButton) {
00656 switch (QApplication::keyboardModifiers()){
00657 case Qt::NoModifier:
00658 setXRotation(xRot - 8 * dy);
00659 setYRotation(yRot + 8 * dx);
00660 break;
00661 case Qt::ControlModifier:
00662 setXRotation(xRot - 8 * dy);
00663 setZRotation(zRot + 8 * dx);
00664 break;
00665 case Qt::ShiftModifier:
00666
00667 xTra += (-zTra/50.0)*dx/200.0;
00668 yTra -= (-zTra/50.0)*dy/200.0;
00669 }
00670 clearAndUpdate();
00671 } else if (event->buttons() & Qt::MidButton) {
00672
00673 xTra += (-zTra/50.0)*dx/200.0;
00674 yTra -= (-zTra/50.0)*dy/200.0;
00675 clearAndUpdate();
00676 }
00677
00678 lastPos = event->pos();
00679 }
00680
00681 void GLViewer::updateTransforms(QList<QMatrix4x4>* transforms){
00682 ROS_WARN_COND(transforms->size() < cloud_matrices->size(), "Got less transforms than before!");
00683
00684
00685 QList<QMatrix4x4>* cloud_matrices_tmp = cloud_matrices;
00686 cloud_matrices = transforms;
00687 ROS_DEBUG("New Cloud matrices size: %d", cloud_matrices->size());
00688
00689
00690 delete cloud_matrices_tmp;
00691 }
00692
00693 void GLViewer::addPointCloud(pointcloud_type * pc, QMatrix4x4 transform){
00694 ROS_DEBUG("pc pointer in addPointCloud: %p (this is %p in thread %d)", pc, this, (unsigned int)QThread::currentThreadId());
00695 ParameterServer* ps = ParameterServer::instance();
00696 std::string display_type = ps->get<std::string>("cloud_display_type");
00697 if(!pc->isOrganized() || ps->get<double>("squared_meshing_threshold") < 0){
00698 pointCloud2GLPoints(pc);
00699 } else {
00700 if(display_type == "TRIANGLES"){
00701 pointCloud2GLTriangleList(pc);
00702 } else if(display_type == "POINTS"){
00703 pointCloud2GLPoints(pc);
00704 } else if(display_type == "ELLIPSOIDS"){
00705 pointCloud2GLEllipsoids(pc);
00706 } else if(display_type == "NONE"){
00707 cloud_list_indices.push_back(0);
00708 } else {
00709 pointCloud2GLStrip(pc);
00710 }
00711 }
00712 cloud_matrices->push_back(transform);
00713 Q_EMIT cloudRendered(pc);
00714 non_interactive_update_ = true;
00715 ScopedTimer s("Rendering", false);
00716 clearAndUpdate();
00717 if(s.elapsed() > 0.05) {
00718 fast_rendering_step_++;
00719 ROS_INFO("Increased renderer skipto every %d.", fast_rendering_step_);
00720 } else if(s.elapsed() < 0.01 && fast_rendering_step_ > 1) {
00721 fast_rendering_step_--;
00722 ROS_INFO("Decreased renderer skip to every %d.", fast_rendering_step_);
00723 } else
00724 ROS_INFO("No change to renderer skip (%d).", fast_rendering_step_);
00725 non_interactive_update_ = false;
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735 }
00736
00737 void GLViewer::addFeatures(const std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> >* feature_locations_3d)
00738 {
00739 ScopedTimer s(__FUNCTION__);
00740 ROS_DEBUG("Making GL list from feature points");
00741 GLuint feature_list_index = glGenLists(1);
00742 if(!feature_list_index) {
00743 ROS_ERROR("No display list could be created");
00744 return;
00745 }
00746 glNewList(feature_list_index, GL_COMPILE);
00747 feature_list_indices.push_back(feature_list_index);
00748 glLineWidth(3*ParameterServer::instance()->get<double>("gl_point_size"));
00749 glBegin(GL_LINES);
00750 float r = (float)rand()/(float)RAND_MAX;
00751 float g = (float)rand()/(float)RAND_MAX;
00752 float b = (float)rand()/(float)RAND_MAX;
00753 BOOST_FOREACH(const Eigen::Vector4f& ft, *feature_locations_3d)
00754 {
00755 if(std::isfinite(ft[2])){
00756 glColor4f(r,g,b, 1.0);
00757
00758 glVertex3f(ft[0], ft[1], ft[2]);
00759 glColor4f(r,g,b, 0.0);
00760 glVertex3f(ft[0], ft[1], ft[2]-depth_std_dev(ft[2]));
00761 }
00762 }
00763 glEnd();
00764 glLineWidth(1.0);
00765 glEndList();
00766 }
00767
00768 inline float squaredEuclideanDistance(point_type p1, point_type p2){
00769 float dx = p1.x - p2.x;
00770 float dy = p1.y - p2.y;
00771 float dz = p1.z - p2.z;
00772 return dx*dx + dy*dy + dz*dz;
00773 }
00774
00775
00776 void GLViewer::pointCloud2GLStrip(pointcloud_type * pc){
00777 ScopedTimer s(__FUNCTION__);
00778 ROS_DEBUG("Making GL list from point-cloud pointer %p in thread %d", pc, (unsigned int)QThread::currentThreadId());
00779 GLuint cloud_list_index = glGenLists(1);
00780 if(!cloud_list_index) {
00781 ROS_ERROR("No display list could be created");
00782 return;
00783 }
00784 const float mesh_thresh = ParameterServer::instance()->get<double>("squared_meshing_threshold");
00785 const float max_depth = ParameterServer::instance()->get<double>("maximum_depth");
00786 glNewList(cloud_list_index, GL_COMPILE);
00787
00788 point_type origin;
00789 origin.x = 0;
00790 origin.y = 0;
00791 origin.z = 0;
00792
00793 float depth;
00794 bool strip_on = false, flip = false;
00795 const int w=pc->width, h=pc->height;
00796 unsigned char b,g,r;
00797 const int step = ParameterServer::instance()->get<int>("visualization_skip_step");
00798 for( int y = 0; y < h-step; y+=step){
00799 for( int x = 0; x < w-step; x+=step){
00800 using namespace pcl;
00801 if(!strip_on){
00802 const point_type* ll = &pc->points[(x)+(y+step)*w];
00803 if(!validXYZ(*ll, max_depth)) continue;
00804 const point_type* ur = &pc->points[(x+step)+y*w];
00805 if(!validXYZ(*ur, max_depth)) continue;
00806
00807 const point_type* ul = &pc->points[x+y*w];
00808 if(validXYZ(*ul, max_depth)){
00809 depth = squaredEuclideanDistance(*ul,origin);
00810 if (squaredEuclideanDistance(*ul,*ll)/depth <= mesh_thresh and
00811 squaredEuclideanDistance(*ul,*ll)/depth <= mesh_thresh and
00812 squaredEuclideanDistance(*ur,*ll)/depth <= mesh_thresh){
00813 glBegin(GL_TRIANGLE_STRIP);
00814 strip_on = true;
00815 flip = false;
00816
00817
00818 setGLColor(*ul);
00819
00820
00821 glVertex3f(ul->x, ul->y, ul->z);
00822 }
00823 }
00824 if(!strip_on) {
00825 const point_type* lr = &pc->points[(x+step)+(y+step)*w];
00826 if(!validXYZ(*lr, max_depth)) {
00827
00828
00829 x++;
00830 continue;
00831 } else {
00832 depth = squaredEuclideanDistance(*ur,origin);
00833 if (squaredEuclideanDistance(*ur,*ll)/depth <= mesh_thresh and
00834 squaredEuclideanDistance(*lr,*ll)/depth <= mesh_thresh and
00835 squaredEuclideanDistance(*ur,*lr)/depth <= mesh_thresh){
00836 glBegin(GL_TRIANGLE_STRIP);
00837 strip_on = true;
00838 flip = true;
00839 }
00840 }
00841 }
00842 if(strip_on) {
00843 setGLColor(*ll);
00844
00845
00846 glVertex3f(ll->x, ll->y, ll->z);
00847 }
00848 continue;
00849 }
00850 else
00851 {
00852 const point_type* ul;
00853 if(flip){ ul = &pc->points[(x)+(y+step)*w]; }
00854 else { ul = &pc->points[x+y*w]; }
00855 if(validXYZ(*ul, max_depth)){
00856 depth = squaredEuclideanDistance(*ul,origin);
00857 if (squaredEuclideanDistance(*ul,*(ul-step))/depth > mesh_thresh){
00858 glEnd();
00859 strip_on = false;
00860 continue;
00861 }
00862
00863
00864 setGLColor(*ul);
00865
00866
00867 glVertex3f(ul->x, ul->y, ul->z);
00868 } else {
00869 glEnd();
00870 strip_on = false;
00871 continue;
00872 }
00873
00874 const point_type* ll;
00875 if(flip){ ll = &pc->points[x+y*w]; }
00876 else { ll = &pc->points[(x)+(y+step)*w]; }
00877 if(validXYZ(*ll, max_depth)){
00878 depth = squaredEuclideanDistance(*ll,origin);
00879 if (squaredEuclideanDistance(*ul,*ll)/depth > mesh_thresh or
00880 squaredEuclideanDistance(*ul,*(ul-step))/depth > mesh_thresh or
00881 squaredEuclideanDistance(*ll,*(ll-step))/depth > mesh_thresh){
00882 glEnd();
00883 strip_on = false;
00884 continue;
00885 }
00886 setGLColor(*ul);
00887
00888 glVertex3f(ll->x, ll->y, ll->z);
00889 } else {
00890 glEnd();
00891 strip_on = false;
00892 continue;
00893 }
00894 }
00895 }
00896 if(strip_on) glEnd();
00897 strip_on = false;
00898 }
00899 ROS_DEBUG("Compiled pointcloud into list %i", cloud_list_index);
00900 glEndList();
00901 cloud_list_indices.push_back(cloud_list_index);
00902
00903
00904
00905
00906 }
00907
00908 void GLViewer::deleteLastNode(){
00909 if(cloud_list_indices.size() <= 1){
00910 this->reset();
00911 return;
00912 }
00913 GLuint nodeId = cloud_list_indices.back();
00914 cloud_list_indices.pop_back();
00915 glDeleteLists(nodeId,1);
00916 GLuint ftId = feature_list_indices.back();
00917 feature_list_indices.pop_back();
00918 glDeleteLists(ftId,1);
00919 }
00920
00922 void GLViewer::pointCloud2GLEllipsoids(pointcloud_type * pc){
00923 ScopedTimer s(__FUNCTION__);
00924 ROS_DEBUG("Making GL list from point-cloud pointer %p in thread %d", pc, (unsigned int)QThread::currentThreadId());
00925 GLuint cloud_list_index = glGenLists(1);
00926 if(!cloud_list_index) {
00927 ROS_ERROR("No display list could be created");
00928 return;
00929 }
00930 cloud_list_indices.push_back(cloud_list_index);
00931 glNewList(cloud_list_index, GL_COMPILE);
00932
00933 point_type origin;
00934 origin.x = 0;
00935 origin.y = 0;
00936 origin.z = 0;
00937
00938 const float max_depth = ParameterServer::instance()->get<double>("maximum_depth");
00939 float depth;
00940 unsigned int w=pc->width, h=pc->height;
00941 for(unsigned int x = 0; x < w; x++){
00942 for(unsigned int y = 0; y < h; y++){
00943
00944 const point_type& p = pc->points[x+y*w];
00945 if(!(validXYZ(p, max_depth))) continue;
00946 setGLColor(p);
00947 drawEllipsoid(0.001*p.z, 0.001*p.z, depth_std_dev(p.z), p.getVector4fMap());
00948 }
00949 }
00950 glEnd();
00951 ROS_DEBUG("Compiled pointcloud into list %i", cloud_list_index);
00952 glEndList();
00953 }
00954
00955 void GLViewer::pointCloud2GLPoints(pointcloud_type * pc){
00956 ScopedTimer s(__FUNCTION__);
00957 ROS_DEBUG("Making GL list from point-cloud pointer %p in thread %d", pc, (unsigned int)QThread::currentThreadId());
00958 GLuint cloud_list_index = glGenLists(1);
00959 if(!cloud_list_index) {
00960 ROS_ERROR("No display list could be created");
00961 return;
00962 }
00963 cloud_list_indices.push_back(cloud_list_index);
00964 glNewList(cloud_list_index, GL_COMPILE);
00965 glBegin(GL_POINTS);
00966
00967 point_type origin;
00968 origin.x = 0;
00969 origin.y = 0;
00970 origin.z = 0;
00971
00972 const float max_depth = ParameterServer::instance()->get<double>("maximum_depth");
00973 float depth;
00974 unsigned int w=pc->width, h=pc->height;
00975 for(unsigned int x = 0; x < w; x++){
00976 for(unsigned int y = 0; y < h; y++){
00977 using namespace pcl;
00978 const point_type* p = &pc->points[x+y*w];
00979 if(!(validXYZ(*p, max_depth))) continue;
00980 setGLColor(*p);
00981 glVertex3f(p->x, p->y, p->z);
00982 }
00983 }
00984 glEnd();
00985 ROS_DEBUG("Compiled pointcloud into list %i", cloud_list_index);
00986 glEndList();
00987 }
00988
00989 void GLViewer::pointCloud2GLTriangleList(pointcloud_type const * pc){
00990 ScopedTimer s(__FUNCTION__);
00991 ROS_DEBUG("Making GL list from point-cloud pointer %p in thread %d", pc, (unsigned int)QThread::currentThreadId());
00992 GLuint cloud_list_index = glGenLists(1);
00993 if(!cloud_list_index) {
00994 ROS_ERROR("No display list could be created");
00995 return;
00996 }
00997 const float mesh_thresh = ParameterServer::instance()->get<double>("squared_meshing_threshold");
00998 cloud_list_indices.push_back(cloud_list_index);
00999 glNewList(cloud_list_index, GL_COMPILE);
01000 glBegin(GL_TRIANGLES);
01001
01002 point_type origin;
01003 origin.x = 0;
01004 origin.y = 0;
01005 origin.z = 0;
01006
01007 const float max_depth = ParameterServer::instance()->get<double>("maximum_depth");
01008 float depth;
01009 unsigned int w=pc->width, h=pc->height;
01010 for(unsigned int x = 0; x < w-1; x++){
01011 for(unsigned int y = 0; y < h-1; y++){
01012 using namespace pcl;
01013
01014 const point_type* pi = &pc->points[x+y*w];
01015
01016 if(!(validXYZ(*pi, max_depth))) continue;
01017 depth = squaredEuclideanDistance(*pi,origin);
01018
01019 const point_type* pl = &pc->points[(x+1)+(y+1)*w];
01020 if(!(validXYZ(*pl, max_depth)) or squaredEuclideanDistance(*pi,*pl)/depth > mesh_thresh)
01021 continue;
01022
01023 const point_type* pj = &pc->points[(x+1)+y*w];
01024 if(validXYZ(*pj, max_depth)
01025 and squaredEuclideanDistance(*pi,*pj)/depth <= mesh_thresh
01026 and squaredEuclideanDistance(*pj,*pl)/depth <= mesh_thresh){
01027
01028 drawTriangle(*pi, *pl, *pj);
01029 }
01030 const point_type* pk = &pc->points[(x)+(y+1)*w];
01031
01032 if(validXYZ(*pk, max_depth)
01033 and squaredEuclideanDistance(*pi,*pk)/depth <= mesh_thresh
01034 and squaredEuclideanDistance(*pk,*pl)/depth <= mesh_thresh){
01035 drawTriangle(*pi, *pk, *pl);
01036 }
01037 }
01038 }
01039 glEnd();
01040 ROS_DEBUG("Compiled pointcloud into list %i", cloud_list_index);
01041 glEndList();
01042 }
01043
01044 void GLViewer::reset(){
01045 if(!cloud_list_indices.empty()){
01046 unsigned int max= cloud_list_indices.size() > feature_list_indices.size()? cloud_list_indices.back() : feature_list_indices.back();
01047 glDeleteLists(1,max);
01048 }
01049 cloud_list_indices.clear();
01050 feature_list_indices.clear();
01051 cloud_matrices->clear();
01052 edge_list_.clear();
01053 clearAndUpdate();
01054 }
01055 QImage GLViewer::renderList(QMatrix4x4 transform, int list_id){
01056 return QImage();
01057 }
01058
01059 void GLViewer::setEdges(const QList<QPair<int, int> >* edge_list){
01060
01061 edge_list_ = *edge_list;
01062 delete edge_list;
01063 }
01064
01065 void GLViewer::drawEdges(){
01066 if(edge_list_.empty()) return;
01067
01068
01069 glBegin(GL_LINES);
01070 glLineWidth(12);
01071 for(int i = 0; i < edge_list_.size(); i++){
01072 int id1 = edge_list_[i].first;
01073 int id2 = edge_list_[i].second;
01074 float x,y,z;
01075 if(cloud_matrices->size() > id1 && cloud_matrices->size() > id2){
01076 if(abs(id1 - id2) == 1){
01077 glColor4f(bg_col_[0],1-bg_col_[1],1-bg_col_[2],1.0);
01078 } else if(abs(id1 - id2) > 20){
01079 glColor4f(1-bg_col_[0],1-bg_col_[1],bg_col_[2],0.4);
01080 } else {
01081 glColor4f(1-bg_col_[0],1-bg_col_[1],1-bg_col_[2],0.4);
01082 }
01083 x = (*cloud_matrices)[id1](0,3);
01084 y = (*cloud_matrices)[id1](1,3);
01085 z = (*cloud_matrices)[id1](2,3);
01086 glVertex3f(x,y,z);
01087 x = (*cloud_matrices)[id2](0,3);
01088 y = (*cloud_matrices)[id2](1,3);
01089 z = (*cloud_matrices)[id2](2,3);
01090 glVertex3f(x,y,z);
01091 }
01092
01093 else ROS_WARN("Not enough cloud matrices (%d) for vertex ids (%d and %d)", cloud_matrices->size(), id1, id2);
01094 }
01095 glEnd();
01096
01097
01098 if(show_tfs_){
01099 glDisable(GL_DEPTH_TEST);
01100 glColor4f(1-bg_col_[0],1-bg_col_[1],1-bg_col_[2],1.0);
01101 for(int i = 0; i < edge_list_.size(); i++){
01102 int id1 = edge_list_[i].first;
01103 int id2 = edge_list_[i].second;
01104 if(cloud_matrices->size() > id1 && cloud_matrices->size() > id2){
01105 Eigen::Vector3f x1((*cloud_matrices)[id1](0,3), (*cloud_matrices)[id1](1,3), (*cloud_matrices)[id1](2,3));
01106 Eigen::Vector3f x2((*cloud_matrices)[id2](0,3), (*cloud_matrices)[id2](1,3), (*cloud_matrices)[id2](2,3));
01107 Eigen::Vector3f dx = x2 - x1;
01108 Eigen::Vector3f xm = x1 + 0.5*dx;
01109
01110 QString edge_info;
01111 edge_info.sprintf("%d-%d:\n(%.2f, %.2f, %.2f)", id1, id2, dx(0), dx(1), dx(2));
01112 this->renderText(xm(0), xm(1), xm(2), edge_info, QFont("Monospace", 6));
01113 }
01114
01115 else ROS_WARN("Not enough cloud matrices (%d) for vertex ids (%d and %d)", cloud_matrices->size(), id1, id2);
01116 }
01117 glEnable(GL_DEPTH_TEST);
01118 }
01119 }
01120
01121
01122 void GLViewer::setViewPoint(QMatrix4x4 new_vp){
01124 viewpoint_tf_ = new_vp.inverted();
01125 }
01126
01127 bool GLViewer::setClickedPosition(int x, int y) {
01128 GLint viewport[4];
01129 GLdouble modelview[16];
01130 GLdouble projection[16];
01131 GLfloat winX, winY, winZ;
01132 GLdouble posX, posY, posZ;
01133
01134 glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
01135 glGetDoublev( GL_PROJECTION_MATRIX, projection );
01136 glGetIntegerv( GL_VIEWPORT, viewport );
01137
01138 winX = (float)x;
01139 winY = (float)viewport[3] - (float)y;
01140 glReadPixels( x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
01141 if(winZ != 1){
01142 gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
01143 ROS_INFO_STREAM((float)winZ << ", [" << posX << "," << posY << "," << posZ << "]");
01144 viewpoint_tf_.setToIdentity();
01145 viewpoint_tf_(0,3) = -posX;
01146 viewpoint_tf_(1,3) = -posY;
01147 viewpoint_tf_(2,3) = -posZ;
01148 Q_EMIT clickedPosition(posX, posY, posZ);
01149 return true;
01150 } else {
01151 return false;
01152 }
01153 }
01154
01155 void GLViewer::toggleTriangulation() {
01156 ROS_INFO("Toggling Triangulation");
01157 if(polygon_mode == GL_FILL){
01158 polygon_mode = GL_POINT;
01159
01160
01161
01162 } else {
01163 polygon_mode = GL_FILL;
01164 }
01165 glPolygonMode(GL_FRONT_AND_BACK, polygon_mode);
01166 clearAndUpdate();
01167 }
01168
01169 void GLViewer::drawToPS(QString filename){
01170 #ifdef GL2PS
01171
01172 FILE *fp = fopen(qPrintable(filename), "wb");
01173 if(!fp) ROS_ERROR("Could not open file %s", qPrintable(filename));
01174 GLint buffsize = 0, state = GL2PS_OVERFLOW;
01175 GLint viewport[4];
01176 char *oldlocale = setlocale(LC_NUMERIC, "C");
01177
01178
01179 glGetIntegerv(GL_VIEWPORT, viewport);
01180
01181 while( state == GL2PS_OVERFLOW ){
01182 buffsize += 1024*1024;
01183 gl2psBeginPage ( "GL View", "RGBD-SLAM", viewport,
01184 GL2PS_PDF, GL2PS_BSP_SORT, GL2PS_SILENT |
01185 GL2PS_SIMPLE_LINE_OFFSET | GL2PS_NO_BLENDING |
01186 GL2PS_OCCLUSION_CULL | GL2PS_BEST_ROOT,
01187 GL_RGBA, 0, NULL, 0, 0, 0, buffsize,
01188 fp, "LatexFile" );
01189 drawClouds(0.0);
01190 state = gl2psEndPage();
01191 }
01192 setlocale(LC_NUMERIC, oldlocale);
01193 fclose(fp);
01194 #else
01195 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."));
01196 #endif
01197 }
01198
01199
01200 inline void GLViewer::clearAndUpdate(){
01201 ScopedTimer s(__FUNCTION__);
01202 makeCurrent();
01203 paintGL();
01204 if(this->format().doubleBuffer())
01205 {
01206 ScopedTimer s("SwapBuffers");
01207 swapBuffers();
01208 }
01209 }
01210
01212 void drawEllipsoid(float fA, float fB, float fC, const Eigen::Vector4f& p)
01213 {
01214 unsigned int uiStacks = 4, uiSlices = 4;
01215 float tStep = (PI) / (float)uiSlices;
01216 float sStep = (PI) / (float)uiStacks;
01217
01218 for(float t = -PI/2; t <= (PI/2)+.0001; t += tStep)
01219 {
01220 glBegin(GL_TRIANGLE_STRIP);
01221 for(float s = -PI; s <= PI+.0001; s += sStep)
01222 {
01223 glVertex3f(p[0] + fA * cos(t) * cos(s),
01224 p[1] + fB * cos(t) * sin(s),
01225 p[2] + fC * sin(t));
01226 glVertex3f(p[0] + fA * cos(t+tStep) * cos(s),
01227 p[1] + fB * cos(t+tStep) * sin(s),
01228 p[2] + fC * sin(t+tStep));
01229 }
01230 glEnd();
01231 }
01232 }
01233
01234 void GLViewer::drawNavigationAxis(int axis_idx, float scale, QString text){
01235 float coords[3] = { 0.0, 0.0, 0.0 };
01236 float colors[3] = { 1.0, 1.0, 1.0 };
01237 colors[axis_idx] = 0.0;
01238 glEnable(GL_BLEND);
01239 glBegin(GL_LINES);
01240 glColor3fv(colors);
01241 coords[axis_idx] = scale * 10;
01242 glVertex3fv(coords);
01243 coords[axis_idx] = -scale * 10;
01244 glVertex3fv(coords);
01245 glEnd();
01246 coords[axis_idx] = -scale;
01247 this->renderText(coords[0],coords[1]+0.01,coords[2],text, QFont("Monospace", 8));
01248 }
01249 void GLViewer::setRenderable(Renderable* r){
01250 ROS_INFO("Setting Renderable");
01251 external_renderable = (Renderable*)r;
01252 }
01253
01254 #else //ifndef DUMMYGLVIEWER (ARM Hardware)
01255 #include "glviewer.h"
01256
01257 GLViewer::GLViewer(QWidget *parent) : QGLWidget(parent) { }
01258 GLViewer::~GLViewer() { }
01259 void GLViewer::initialPosition() { }
01260 QSize GLViewer::minimumSizeHint() const { return QSize(0, 0); }
01261 QSize GLViewer::sizeHint() const { return QSize(0, 0); }
01262 void GLViewer::setXRotation(int angle) { }
01263 void GLViewer::setYRotation(int angle) { }
01264 void GLViewer::setRotationGrid(double rot_step_in_degree) { }
01265 void GLViewer::setStereoShift(double shift) { }
01266 void GLViewer::initializeGL() { }
01267 void GLViewer::drawTriangle(const point_type& p1, const point_type& p2, const point_type& p3){ }
01268 void GLViewer::drawGrid(){ }
01269 void GLViewer::drawAxes(float scale, float thickness){ }
01270 void GLViewer::makeCurrent(){ }
01271 void GLViewer::paintGL() { }
01272 void GLViewer::drawRenderable() { }
01273 void GLViewer::drawOneCloud(int i) { }
01274 void GLViewer::drawClouds(float xshift) { }
01275 void GLViewer::resizeGL(int width, int height) { }
01276 void GLViewer::mouseDoubleClickEvent(QMouseEvent *event) { }
01277 void GLViewer::toggleStereo(bool flag){ }
01278 void GLViewer::toggleBackgroundColor(bool flag){ }
01279 void GLViewer::toggleShowFeatures(bool flag){ }
01280 void GLViewer::toggleShowOctoMap(bool flag){ }
01281 void GLViewer::toggleShowClouds(bool flag){ }
01282 void GLViewer::toggleShowTFs(bool flag){ }
01283 void GLViewer::toggleShowGrid(bool flag){ }
01284 void GLViewer::toggleShowIDs(bool flag){ }
01285 void GLViewer::toggleShowEdges(bool flag){ }
01286 void GLViewer::toggleShowPoses(bool flag){ }
01287 void GLViewer::toggleFollowMode(bool flag){ }
01288 void GLViewer::mouseReleaseEvent(QMouseEvent *event) { }
01289 void GLViewer::mousePressEvent(QMouseEvent *event) { }
01290 void GLViewer::wheelEvent(QWheelEvent *event) { }
01291 void GLViewer::mouseMoveEvent(QMouseEvent *event) { }
01292 void GLViewer::updateTransforms(QList<QMatrix4x4>* transforms){ }
01293 void GLViewer::addPointCloud(pointcloud_type * pc, QMatrix4x4 transform){ }
01294 void GLViewer::addFeatures(const std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> >* feature_locations_3d) { }
01295 void GLViewer::pointCloud2GLStrip(pointcloud_type * pc){ }
01296 void GLViewer::deleteLastNode(){ }
01297 void GLViewer::pointCloud2GLEllipsoids(pointcloud_type * pc){ }
01298 void GLViewer::pointCloud2GLPoints(pointcloud_type * pc){ }
01299 void GLViewer::pointCloud2GLTriangleList(pointcloud_type const * pc){ }
01300 void GLViewer::reset(){ }
01301 QImage GLViewer::renderList(QMatrix4x4 transform, int list_id){ return QImage(); }
01302 void GLViewer::setEdges(const QList<QPair<int, int> >* edge_list){ }
01303 void GLViewer::drawEdges(){ }
01304 void GLViewer::setViewPoint(QMatrix4x4 new_vp){ }
01305 bool GLViewer::setClickedPosition(int x, int y) { }
01306 void GLViewer::toggleTriangulation() { }
01307 void GLViewer::drawToPS(QString filename){ }
01308 void GLViewer::clearAndUpdate(){ }
01309 void GLViewer::drawNavigationAxis(int axis_idx, float scale, QString text){ }
01310 void GLViewer::setRenderable(Renderable* r){ }
01311
01312 #endif