QtBaseViewer.cc 71.2 KB
Newer Older
Jan Möbius's avatar
Jan Möbius committed
1 2 3
/*===========================================================================*\
*                                                                            *
*                              OpenFlipper                                   *
Jan Möbius's avatar
Jan Möbius committed
4
*      Copyright (C) 2001-2014 by Computer Graphics Group, RWTH Aachen       *
Jan Möbius's avatar
Jan Möbius committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
*                           www.openflipper.org                              *
*                                                                            *
*--------------------------------------------------------------------------- *
*  This file is part of OpenFlipper.                                         *
*                                                                            *
*  OpenFlipper is free software: you can redistribute it and/or modify       *
*  it under the terms of the GNU Lesser General Public License as            *
*  published by the Free Software Foundation, either version 3 of            *
*  the License, or (at your option) any later version with the               *
*  following exceptions:                                                     *
*                                                                            *
*  If other files instantiate templates or use macros                        *
*  or inline functions from this file, or you compile this file and          *
*  link it with other files to produce an executable, this file does         *
*  not by itself cause the resulting executable to be covered by the         *
*  GNU Lesser General Public License. This exception does not however        *
*  invalidate any other reasons why the executable file might be             *
*  covered by the GNU Lesser General Public License.                         *
*                                                                            *
*  OpenFlipper is distributed in the hope that it will be useful,            *
*  but WITHOUT ANY WARRANTY; without even the implied warranty of            *
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
*  GNU Lesser General Public License for more details.                       *
*                                                                            *
*  You should have received a copy of the GNU LesserGeneral Public           *
*  License along with OpenFlipper. If not,                                   *
*  see <http://www.gnu.org/licenses/>.                                       *
*                                                                            *
33 34 35
\*===========================================================================*/

/*===========================================================================*\
Jan Möbius's avatar
Jan Möbius committed
36 37 38 39 40
*                                                                            *
*   $Revision$                                                       *
*   $LastChangedBy$                                                *
*   $Date$                     *
*                                                                            *
41
\*===========================================================================*/
Jan Möbius's avatar
 
Jan Möbius committed
42 43 44 45 46 47




//=============================================================================
//
Jan Möbius's avatar
 
Jan Möbius committed
48
//  CLASS glViewer - IMPLEMENTATION
Jan Möbius's avatar
 
Jan Möbius committed
49 50 51 52 53 54 55
//
//=============================================================================


//== INCLUDES =================================================================

#include "QtBaseViewer.hh"
Jan Möbius's avatar
Jan Möbius committed
56
#include "QtGLViewerLayout.hh"
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
57
#include "CursorPainter.hh"
Jan Möbius's avatar
Jan Möbius committed
58

Jan Möbius's avatar
 
Jan Möbius committed
59 60
#include <ACG/QtWidgets/QtWheel.hh>
#include <ACG/Scenegraph/DrawModes.hh>
61
#include <ACG/Scenegraph/CoordsysNode.hh>
Jan Möbius's avatar
Jan Möbius committed
62
#include <ACG/Scenegraph/SceneGraphAnalysis.hh>
Jan Möbius's avatar
 
Jan Möbius committed
63
#include <ACG/GL/gl.hh>
64 65
#include <ACG/GL/GLError.hh>
#include <ACG/GL/FBO.hh>
66
#include <ACG/GL/IRenderer.hh>
Jan Möbius's avatar
 
Jan Möbius committed
67 68 69

#include <iostream>
#include <string>
70
#include <cassert>
Jan Möbius's avatar
 
Jan Möbius committed
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

#include <QMimeData>
#include <QToolButton>
#include <QFrame>

#include <QClipboard>
#include <QApplication>
#include <QSplitter>
#include <QLayout>
#include <QPushButton>
#include <QLabel>
#include <QImage>
#include <QColorDialog>
#include <QToolTip>
#include <QTextStream>
#include <QDateTime>
#include <QTimer>

#include <QDesktopWidget>
#include <QMouseEvent>
#include <QVBoxLayout>
#include <QKeyEvent>
#include <QGridLayout>
#include <QContextMenuEvent>
#include <QWheelEvent>
#include <QDropEvent>
#include <QPixmap>
#include <QMenu>
#include <QVariant>
#include <QButtonGroup>
#include <QToolBar>

103 104
#include <QGraphicsView>
#include <QGraphicsScene>
Jan Möbius's avatar
 
Jan Möbius committed
105 106 107
#include <QGraphicsWidget>
#include <QGraphicsGridLayout>
#include <QGraphicsProxyWidget>
Jan Möbius's avatar
 
Jan Möbius committed
108 109
#include <QPainter>
#include <QPaintEngine>
Jan Möbius's avatar
 
Jan Möbius committed
110

111 112
#include <QImageWriter>

113 114 115 116 117 118 119 120
#if QT_VERSION < 0x050000
  #include <QGLFramebufferObject>
#else // QT_VERSION > 0x050000
  #undef QT_NO_OPENGL
  #include <QOpenGLFramebufferObject>
  #define QT_NO_OPENGL
#endif //QT_VERSION < 0x050000

Jan Möbius's avatar
 
Jan Möbius committed
121 122 123 124 125 126 127 128
#ifdef max
#  undef max
#endif

#ifdef min
#  undef min
#endif

129
#include <OpenFlipper/BasePlugin/PluginFunctions.hh>
Jan Möbius's avatar
Jan Möbius committed
130
#include <OpenFlipper/common/ViewObjectMarker.hh>
Jan Möbius's avatar
 
Jan Möbius committed
131

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
132 133
#include <OpenFlipper/common/GlobalOptions.hh>

134 135
#include <QGLFramebufferObject>

136
#include <OpenFlipper/common/RendererInfo.hh>
137 138
#include <OpenFlipper/BasePlugin/PostProcessorInterface.hh>

Jan Möbius's avatar
 
Jan Möbius committed
139 140 141 142 143 144
//== NAMESPACES ===============================================================



//== IMPLEMENTATION ==========================================================

145
static const char          COPY_PASTE_VIEW_START_STRING[] =
Jan Möbius's avatar
 
Jan Möbius committed
146 147 148 149 150
  "ACG::QtWidgets::QGLViewerWidget encoded view";

//== IMPLEMENTATION ==========================================================


151
glViewer::glViewer( QGraphicsScene* _scene,
152
                    QGLWidget* _glWidget,
153
                    Viewer::ViewerProperties& _properties,
154
                    QGraphicsWidget* _parent) :
Jan Möbius's avatar
 
Jan Möbius committed
155
  QGraphicsWidget(_parent),
Jan Möbius's avatar
 
Jan Möbius committed
156 157
  glareaGrabbed_(false),
  projectionUpdateLocked_(false),
Jan Möbius's avatar
 
Jan Möbius committed
158 159
  glScene_(_scene),
  glWidget_(_glWidget),
Jan Möbius's avatar
Jan Möbius committed
160 161 162
  pickCache_(0),
  updatePickCache_(true),
  pickCacheSupported_(true),
163
  constrainedRotationAxis_(std::numeric_limits<double>::quiet_NaN(), 0, 0),
164
  clickEvent_(QEvent::MouseButtonPress, QPoint (), Qt::NoButton, Qt::NoButton, Qt::NoModifier),
Dirk Wilden's avatar
Dirk Wilden committed
165
  properties_(_properties),
166
  glstate_(0),
Jan Möbius's avatar
Jan Möbius committed
167 168 169 170 171
  initialized_(false),
  flyAnimationPerspective_(0),
  flyAnimationOrthogonal_(0),
  flyAngle_(0.0),
  currentAnimationPos_(0.0),
172
  flyMoveBack_(false)
Jan Möbius's avatar
 
Jan Möbius committed
173 174 175
{

  // widget stuff
176
  createWidgets();
Jan Möbius's avatar
 
Jan Möbius committed
177 178 179

  // bind GL context to GL state class
  glstate_ = new ACG::GLState();
180 181
  properties_.setglState( glstate_ );

Jan Möbius's avatar
 
Jan Möbius committed
182 183
  // state
  isRotating_       = false;
Mike Kremer's avatar
Mike Kremer committed
184
  lookAround_       = false;
Jan Möbius's avatar
 
Jan Möbius committed
185 186 187

  sceneGraphRoot_   = 0;

188
  normalsMode_      = NORMALIZE_NORMALS;
Jan Möbius's avatar
 
Jan Möbius committed
189
  projectionMode_   = PERSPECTIVE_PROJECTION;
Jan Möbius's avatar
Jan Möbius committed
190
  navigationMode_   = NORMAL_NAVIGATION;
191

Jan Möbius's avatar
 
Jan Möbius committed
192 193 194 195 196 197 198 199 200 201 202 203 204 205
  trackMouse_ = false;

  // Note: we start locked (initialization of updateLocked_)
  // will be unlocked in initializeGL()

  QSizePolicy sp = sizePolicy();
  sp.setHorizontalPolicy( QSizePolicy::Expanding );
  sp.setVerticalPolicy( QSizePolicy::Expanding );
  sp.setHorizontalStretch( 1 );
  sp.setVerticalStretch( 1 );
  setSizePolicy( sp );

  redrawTime_.start ();

206 207 208 209
  // timer for animation
  timer_ = new QTimer( this );
  connect( timer_, SIGNAL(timeout()), this, SLOT( slotAnimation()) );

210 211
  fovyModifier_ = 1.0;

212 213 214
  allowRotation_ = true;


Jan Möbius's avatar
 
Jan Möbius committed
215 216 217
  connect( &properties_,SIGNAL(updated()), this, SLOT( slotPropertiesUpdated() ) );


Dirk Wilden's avatar
Dirk Wilden committed
218 219 220
  //check for updated properties once
  slotPropertiesUpdated();

Jan Möbius's avatar
 
Jan Möbius committed
221
  setAcceptDrops(true);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
222

223
  setHome();
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
224

225 226
  clickTimer_.setSingleShot (true);
  connect (&clickTimer_, SIGNAL(timeout ()), this, SLOT(slotClickTimeout ()));
Jan Möbius's avatar
 
Jan Möbius committed
227 228 229 230 231 232
}


//-----------------------------------------------------------------------------


Jan Möbius's avatar
 
Jan Möbius committed
233
glViewer::~glViewer()
Jan Möbius's avatar
 
Jan Möbius committed
234 235 236 237 238 239 240 241
{
  delete glstate_;
}


//-----------------------------------------------------------------------------


242 243 244 245 246
//QSizeF
//glViewer::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const
//{
//  return QSizeF( 600, 600 );
//}
Jan Möbius's avatar
 
Jan Möbius committed
247 248 249 250

//-----------------------------------------------------------------------------


Jan Möbius's avatar
 
Jan Möbius committed
251
void glViewer::makeCurrent() {
Jan Möbius's avatar
 
Jan Möbius committed
252 253 254
  glWidget_->makeCurrent();
}

Jan Möbius's avatar
 
Jan Möbius committed
255
void glViewer::swapBuffers() {
Jan Möbius's avatar
 
Jan Möbius committed
256 257 258 259 260 261
  glWidget_->swapBuffers();
}


//-----------------------------------------------------------------------------

Jan Möbius's avatar
Jan Möbius committed
262 263 264 265 266
void glViewer::sceneGraph(ACG::SceneGraph::BaseNode* _root,
                          unsigned int               _maxPasses,
                          ACG::Vec3d                 _bbmin,
                          ACG::Vec3d                 _bbmax,
                          const bool _resetTrackBall)
Jan Möbius's avatar
 
Jan Möbius committed
267 268 269
{
  sceneGraphRoot_ = _root;

Jan Möbius's avatar
Jan Möbius committed
270
  if (sceneGraphRoot_ )
Jan Möbius's avatar
 
Jan Möbius committed
271 272
  {

Jan Möbius's avatar
Jan Möbius committed
273 274
    // set max number of render pass
    glstate_->set_max_render_passes(_maxPasses);
Jan Möbius's avatar
Jan Möbius committed
275
    
Jan Möbius's avatar
Jan Möbius committed
276 277 278
    if ( ( _bbmin[0] > _bbmax[0] ) ||
         ( _bbmin[1] > _bbmax[1] ) ||
         ( _bbmin[2] > _bbmax[2] )   ) {
279 280
      
      // Invalid bounding box, try to recover
281
      setScenePos( properties_.sceneCenter() , properties_.sceneRadius(), _resetTrackBall );
282 283
    
      // Update bounding box to match the scene geometry after recovery
Jan Möbius's avatar
Jan Möbius committed
284 285
      _bbmin = ACG::Vec3d(-1.0,-1.0,-1.0);
      _bbmax = ACG::Vec3d( 1.0, 1.0, 1.0);
Jan Möbius's avatar
Jan Möbius committed
286 287
    } else {
      
288
      // For very small scenes, we set the scene radius to 0.1
Jan Möbius's avatar
Jan Möbius committed
289
      // otherwise we take the real radius
Jan Möbius's avatar
Jan Möbius committed
290 291
      if ( ( _bbmax - _bbmin ).max() < OpenFlipperSettings().value("Core/Gui/glViewer/minimalSceneSize",0.1).toDouble() )  {
        setScenePos( ( _bbmin + _bbmax )        * 0.5,
292
                     OpenFlipperSettings().value("Core/Gui/glViewer/minimalSceneSize",0.1).toDouble(),
Jan Möbius's avatar
Jan Möbius committed
293 294 295
                     _resetTrackBall);
                   
      } else {
Jan Möbius's avatar
Jan Möbius committed
296 297
        setScenePos( ( _bbmin + _bbmax )        * 0.5,
                     ( _bbmax - _bbmin ).norm() * 0.5,
Jan Möbius's avatar
Jan Möbius committed
298 299 300 301
                     _resetTrackBall); 
      }
                   
    }
302 303
                   
    // remember the new bounding box for the state
Jan Möbius's avatar
Jan Möbius committed
304
    glstate_->set_bounding_box(_bbmin,_bbmax);
305
    
Jan Möbius's avatar
 
Jan Möbius committed
306
  }
307
  
Jan Möbius's avatar
 
Jan Möbius committed
308 309 310 311 312 313 314 315 316 317

  updateGL();

  emit(signalSceneGraphChanged(sceneGraphRoot_));
}


//-----------------------------------------------------------------------------


Jan Möbius's avatar
 
Jan Möbius committed
318
void glViewer::trackMouse(bool _track)
Jan Möbius's avatar
 
Jan Möbius committed
319 320 321 322 323 324 325
{
  trackMouse_ = _track;
}


//-----------------------------------------------------------------------------

326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
void glViewer::setCoordSysProjection(ProjectionMode _mode) {
  // Find coordsys node
  ACG::SceneGraph::BaseNode* node = 0;
  node = PluginFunctions::getSceneGraphRootNode()->find("Core Coordsys Node");

  // set the projection mode for the coordinate system node
  if (node != 0) {
    ACG::SceneGraph::CoordsysNode* cnode = dynamic_cast<ACG::SceneGraph::CoordsysNode*> (node);
    if (_mode ==  ORTHOGRAPHIC_PROJECTION) {
      cnode->setProjectionMode(ACG::SceneGraph::CoordsysNode::ORTHOGRAPHIC_PROJECTION);
    } else {
      cnode->setProjectionMode(ACG::SceneGraph::CoordsysNode::PERSPECTIVE_PROJECTION);
    }
  }
}


//-----------------------------------------------------------------------------


Jan Möbius's avatar
 
Jan Möbius committed
346
void glViewer::perspectiveProjection()
Jan Möbius's avatar
 
Jan Möbius committed
347 348 349 350 351 352
{
  projectionMode(PERSPECTIVE_PROJECTION);
  updateGL();
}


Jan Möbius's avatar
 
Jan Möbius committed
353
void glViewer::orthographicProjection()
Jan Möbius's avatar
 
Jan Möbius committed
354 355 356 357 358 359
{
  projectionMode(ORTHOGRAPHIC_PROJECTION);
  updateGL();
}


Jan Möbius's avatar
 
Jan Möbius committed
360
void glViewer::toggleProjectionMode()
Jan Möbius's avatar
 
Jan Möbius committed
361 362 363 364 365 366 367 368 369 370
{
  if (projectionMode_ == ORTHOGRAPHIC_PROJECTION)
    projectionMode(PERSPECTIVE_PROJECTION);
  else
    projectionMode(ORTHOGRAPHIC_PROJECTION);

  updateGL();
}


Jan Möbius's avatar
 
Jan Möbius committed
371
void glViewer::projectionMode(ProjectionMode _p)
Jan Möbius's avatar
 
Jan Möbius committed
372 373
{
  if ((projectionMode_ = _p) == ORTHOGRAPHIC_PROJECTION)
374
    emit projectionModeChanged( true );
Jan Möbius's avatar
 
Jan Möbius committed
375
  else
376
    emit projectionModeChanged( false );
Jan Möbius's avatar
 
Jan Möbius committed
377 378

  updateProjectionMatrix();
379

380 381
  setCoordSysProjection(_p);

382
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
383 384
}

385 386 387
void glViewer::toggleNavigationMode()
{
  if (navigationMode_ == NORMAL_NAVIGATION)
Mike Kremer's avatar
Mike Kremer committed
388
    navigationMode(FIRSTPERSON_NAVIGATION);
389 390 391 392 393 394 395 396 397 398 399 400 401
  else
    navigationMode(NORMAL_NAVIGATION);
}


void glViewer::navigationMode(NavigationMode _n)
{
  if ((navigationMode_ = _n) == NORMAL_NAVIGATION)
    emit navigationModeChanged( true );
  else
    emit navigationModeChanged( false );
}

402 403 404 405 406 407 408 409 410 411 412
void glViewer::setFOVY(double _fovy) {
    
  if(_fovy <= 0.0 || _fovy >= 180) {
    std::cerr << "Error: Minimum or maximum fovy angle exceeded!" << std::endl;
    return;
  }
  
  OpenFlipperSettings().setValue("Core/Projection/FOVY", _fovy);
  updateProjectionMatrix();
}

Jan Möbius's avatar
 
Jan Möbius committed
413
void glViewer::updateProjectionMatrix()
Jan Möbius's avatar
 
Jan Möbius committed
414 415 416 417 418 419 420 421
{
  if( projectionUpdateLocked_ )
    return;

  makeCurrent();

  glstate_->reset_projection();

422
  const double aspect = this->aspect_ratio();
423
  // In stereo mode we have to use a perspective matrix
424
  if ( projectionMode_ == PERSPECTIVE_PROJECTION)
Jan Möbius's avatar
 
Jan Möbius committed
425
  {
426

427
    // Get fovy
428
    const double fovy = this->field_of_view_vertical();
429 430

    glstate_->perspective(fovy, (GLdouble) aspect,
431
                          near_plane(), far_plane());
Jan Möbius's avatar
Jan Möbius committed
432 433 434
  }
  else
  {
Jan Möbius's avatar
 
Jan Möbius committed
435

436 437 438
    glstate_->ortho( -ortho_width(), ortho_width(),
                     -ortho_width() / aspect, ortho_width() / aspect,
                     near_plane(), far_plane() );
Jan Möbius's avatar
 
Jan Möbius committed
439
  }
440

Jan Möbius's avatar
 
Jan Möbius committed
441 442 443 444 445 446
}


//-----------------------------------------------------------------------------


447
void glViewer::setScenePos(const ACG::Vec3d& _center, double _radius, const bool _resetTrackBall)
Jan Möbius's avatar
 
Jan Möbius committed
448
{
449
  if(_resetTrackBall) {
450
    properties_.trackballCenter(_center);
451 452
  }

453
  properties_.sceneCenter(_center);
454

455 456
  properties_.sceneRadius(_radius);
  properties_.trackballRadius(_radius);
457

458
  ACG::Vec3d c = glstate_->modelview().transform_point(properties_.sceneCenter());
459

Jan Möbius's avatar
Jan Möbius committed
460 461
  double nearPlane = std::max(0.0001f * properties_.sceneRadius(),  -(c[2] + properties_.sceneRadius()));
  double farPlane  = std::max(0.0002f * properties_.sceneRadius(),  -(c[2] - properties_.sceneRadius()));
462 463

   // Safety check, if near < 0
Jan Möbius's avatar
Jan Möbius committed
464
   if ( nearPlane <= 0.0 ) {
465
     std::cerr << "Error in BaseViewer drawScene, nearplane <= 0.0" << std::endl;
Jan Möbius's avatar
Jan Möbius committed
466
     nearPlane = 0.000000000000001;
467 468 469
   }

  // Safety check. Make sure that they are in the right order
Jan Möbius's avatar
Typo  
Jan Möbius committed
470
  if ( nearPlane > farPlane ) {
471
    std::cerr << "Error in BaseViewer setScenePos, Nearplane > Farplane" << std::endl;
Jan Möbius's avatar
Jan Möbius committed
472
    std::swap(nearPlane,farPlane);
473 474
  }

Jan Möbius's avatar
Jan Möbius committed
475
  properties_.setPlanes(nearPlane,farPlane);
476
  properties_.orthoWidth(_radius);
Jan Möbius's avatar
 
Jan Möbius committed
477

478 479 480 481
  updateProjectionMatrix();
  updateGL();

  emit viewChanged();
482 483 484 485 486 487
}


//----------------------------------------------------------------------------


Jan Möbius's avatar
 
Jan Möbius committed
488
void glViewer::viewingDirection( const ACG::Vec3d& _dir, const ACG::Vec3d& _up )
Jan Möbius's avatar
 
Jan Möbius committed
489 490
{
  // calc eye point for this direction
491
  ACG::Vec3d eye = properties_.sceneCenter() - _dir * ( 3.0 * properties_.sceneRadius());
Jan Möbius's avatar
 
Jan Möbius committed
492 493

  glstate_->reset_modelview();
494
  glstate_->lookAt((ACG::Vec3d)eye, (ACG::Vec3d)properties_.sceneCenter(), (ACG::Vec3d)_up);
495

496
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
497 498
}

499 500 501 502 503 504 505
//-----------------------------------------------------------------------------

void glViewer::lookAt(const ACG::Vec3d& _eye, const ACG::Vec3d& _center, const ACG::Vec3d& _up) {
    
    glstate_->reset_modelview();
    glstate_->lookAt(_eye, _center, _up);
    
506 507
    properties_.sceneCenter( _center );
    properties_.sceneRadius( (properties_.sceneCenter() - _eye).norm() );
508 509 510
    
    emit viewChanged();
}
Jan Möbius's avatar
 
Jan Möbius committed
511 512 513

//-----------------------------------------------------------------------------

Jan Möbius's avatar
 
Jan Möbius committed
514
void glViewer::normalsMode(NormalsMode _mode)
Jan Möbius's avatar
 
Jan Möbius committed
515 516 517 518 519 520
{
  makeCurrent();

  switch(normalsMode_ = _mode)
  {
    case DONT_TOUCH_NORMALS:
521
      ACG::GLState::disable(GL_NORMALIZE);
Jan Möbius's avatar
 
Jan Möbius committed
522 523 524
      break;

    case NORMALIZE_NORMALS:
525
      ACG::GLState::enable(GL_NORMALIZE);
Jan Möbius's avatar
 
Jan Möbius committed
526 527 528 529 530 531 532 533 534 535 536
      break;
  }

  updateGL();
}


//-----------------------------------------------------------------------------


void
Jan Möbius's avatar
 
Jan Möbius committed
537
glViewer::copyToImage( QImage& _image,
Jan Möbius's avatar
Jan Möbius committed
538 539
		       unsigned int _l, unsigned int _t,
		       unsigned int _w, unsigned int _h,
540
			     GLenum /* _buffer */ )
Jan Möbius's avatar
 
Jan Möbius committed
541
{
542 543 544

//    makeCurrent();

Jan Möbius's avatar
Jan Möbius committed
545
  _image = glWidget_->grabFrameBuffer(true).copy (_l, _t, _w, _h).convertToFormat (QImage::Format_RGB32);
Jan Möbius's avatar
 
Jan Möbius committed
546 547 548 549 550 551
}


//-----------------------------------------------------------------------------


Jan Möbius's avatar
 
Jan Möbius committed
552
void glViewer::updateGL()
Jan Möbius's avatar
 
Jan Möbius committed
553
{
Jan Möbius's avatar
 
Jan Möbius committed
554
  if (!properties_.updateLocked() && isVisible() )
Jan Möbius's avatar
 
Jan Möbius committed
555
  {
Jan Möbius's avatar
Jan Möbius committed
556
    updatePickCache_ = true;
Jan Möbius's avatar
 
Jan Möbius committed
557
    update();
558 559

    emit viewUpdated();
Jan Möbius's avatar
 
Jan Möbius committed
560 561 562 563 564 565 566 567
  }
}



//-----------------------------------------------------------------------------


Jan Möbius's avatar
 
Jan Möbius committed
568
void glViewer::drawScene()
Jan Möbius's avatar
 
Jan Möbius committed
569
{
570 571 572 573
  
  // Inside the glWidget rendering, the system should not send extra updates
  properties_.blockSignals(true);
  
Jan Möbius's avatar
 
Jan Möbius committed
574 575 576
  QTime  timer;
  timer.start();

Jan Möbius's avatar
 
Jan Möbius committed
577 578 579 580
  // *****************************************************************
  // Adjust clipping planes
  // *****************************************************************
  // Far plane
581
  ACG::Vec3d c = glstate_->modelview().transform_point(properties_.sceneCenter());
Jan Möbius's avatar
 
Jan Möbius committed
582

Jan Möbius's avatar
Jan Möbius committed
583 584
  double nearPlane = std::max(0.0001f * properties_.sceneRadius(),  -(c[2] + properties_.sceneRadius()));
  double farPlane  = std::max(0.0002f * properties_.sceneRadius(),  -(c[2] - properties_.sceneRadius()));
585 586

  // Safety check, if near < 0
Jan Möbius's avatar
Jan Möbius committed
587
  if ( nearPlane <= 0.0 ) {
588
    std::cerr << "Error in BaseViewer drawScene, nearplane < 0" << std::endl;
Jan Möbius's avatar
Jan Möbius committed
589
    nearPlane = 0.000000000000001;
590 591 592
  }

  // Safety check. Make sure that they are in the right order
Jan Möbius's avatar
Jan Möbius committed
593
  if ( nearPlane > farPlane ) {
594
    std::cerr << "Error in BaseViewer drawScene, Nearplane > Farplane" << std::endl;
Jan Möbius's avatar
Jan Möbius committed
595
    std::swap(nearPlane,farPlane);
596
  }
Jan Möbius's avatar
 
Jan Möbius committed
597

Jan Möbius's avatar
Jan Möbius committed
598
  properties_.setPlanes(nearPlane,farPlane);
Jan Möbius's avatar
 
Jan Möbius committed
599

Jan Möbius's avatar
 
Jan Möbius committed
600 601 602 603 604 605
  updateProjectionMatrix();

  // store time since last repaint in gl state and restart timer
  glstate_->set_msSinceLastRedraw (redrawTime_.restart ());

  makeCurrent();
606

Jan Möbius's avatar
Jan Möbius committed
607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
  // draw mono or stereo
  // If stereo mode is selected, we have to provide multiple ways of rendering.

  // 1. Default internal pipeline : Directly to output buffer (no stereo support!)
  // 2. Non default : Non-stereo Directly to output buffer (no stereo support!)
  //
  //

//  if (OpenFlipper::Options::stereoMode () == OpenFlipper::Options::OpenGL && OpenFlipper::Options::glStereo ())
//  {
//    // Stereo      : Hardware support (OpenGL stereo : left and right buffer with offset eyes)
//
//    return;
//  }
//  else if (OpenFlipper::Options::stereoMode () == OpenFlipper::Options::AnaglyphCustom && customAnaglyphSupported_)
//  {
//    //Stereo      : No Hardware support (Left and right frame buffer with offset eyes)
//  } else {
//
//  }

628 629 630 631 632 633 634 635 636 637
  // Clear back buffer here:
  // Render plugins do not have to worry about using scissor test for clearing their viewports later on.
  glClearColor(properties_.backgroundColor()[0], properties_.backgroundColor()[1], properties_.backgroundColor()[2], 1.0f);
  GLint curViewport[4];
  glGetIntegerv(GL_VIEWPORT, curViewport);
  glScissor(curViewport[0], curViewport[1], curViewport[2], curViewport[3]);
  glEnable(GL_SCISSOR_TEST);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glDisable(GL_SCISSOR_TEST);

Jan Möbius's avatar
Jan Möbius committed
638

639
  // Check if we use build in default renderer
Jan Möbius's avatar
Jan Möbius committed
640
  if ( renderManager().activeId( properties_.viewerId() ) == 0 ) {
641
    drawScene_mono();
Jan Möbius's avatar
Jan Möbius committed
642
  } else {
643 644 645 646 647 648 649 650 651
    RenderInterface* renderPlugin = renderManager().active( properties_.viewerId() )->plugin;

    // eventually set viewer id in IRenderer
    ACG::IRenderer* shaderRenderPlugin = dynamic_cast<ACG::IRenderer*>(renderPlugin);

    if (shaderRenderPlugin)
      shaderRenderPlugin->setViewerID( properties_.viewerId() );

    renderPlugin->render(glstate_,properties_);
Jan Möbius's avatar
Jan Möbius committed
652
  }
653
  checkGLError();
Jan Möbius's avatar
Jan Möbius committed
654 655


656 657
  // =================================================================================
  // Post-Processing pipeline
Jan Möbius's avatar
Jan Möbius committed
658 659


660
  const int numPostProcessors = postProcessorManager().numActive(properties_.viewerId());
Jan Möbius's avatar
Jan Möbius committed
661

662 663 664 665
  if (numPostProcessors)
  {
    GLuint backbufferFbo = 0;
    glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&backbufferFbo);
Jan Möbius's avatar
Jan Möbius committed
666 667


668
    updatePostProcessingBufs(glstate_->viewport_width(),glstate_->viewport_height());
Jan Möbius's avatar
Jan Möbius committed
669

670
    readBackBuffer(glstate_);
Jan Möbius's avatar
Jan Möbius committed
671

672 673 674
    // 1st post processing source: active fbo
    int postProcSrc = 1;
    PostProcessorInput postProcInput;
Jan Möbius's avatar
Jan Möbius committed
675

676 677 678 679
    postProcInput.colorTex_ = readBackFbo_.getAttachment(GL_COLOR_ATTACHMENT0);
    postProcInput.depthTex_ = readBackFbo_.getAttachment(GL_DEPTH_ATTACHMENT);
    postProcInput.width     = readBackFbo_.width();
    postProcInput.height    = readBackFbo_.height();
Jan Möbius's avatar
Jan Möbius committed
680

681 682
    // execute post processing chain with 2 FBOs
    for (int i = 0; i < numPostProcessors; ++i)  {
Jan Möbius's avatar
Jan Möbius committed
683

684
      int postProcTarget = 1 - postProcSrc;
Jan Möbius's avatar
Jan Möbius committed
685

686
      GLuint targetFBO = postProcessFBO_[postProcTarget].getFboID();
Jan Möbius's avatar
Jan Möbius committed
687

688 689 690
      // write to back buffer in last step
      if (i + 1 == numPostProcessors)
        targetFBO = backbufferFbo;
Jan Möbius's avatar
Jan Möbius committed
691

692 693 694 695
      // apply post processor
      PostProcessorInfo* proc = postProcessorManager().active( properties_.viewerId(), i );
      if (proc && proc->plugin)
        proc->plugin->postProcess(glstate_, postProcInput, targetFBO);
Jan Möbius's avatar
Jan Möbius committed
696 697


698 699
      // swap target/source fbo
      postProcSrc = postProcTarget;
Jan Möbius's avatar
Jan Möbius committed
700

701 702
      postProcInput.colorTex_ = postProcessFBO_[postProcSrc].getAttachment(GL_COLOR_ATTACHMENT0);
    }
703
  }
704
  
Jan Möbius's avatar
Jan Möbius committed
705 706 707 708 709 710

  // =================================================================================

  // unbind vbo for qt log window
  glBindBuffer(GL_ARRAY_BUFFER, 0);

711 712 713
  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, 0);

Jan Möbius's avatar
Jan Möbius committed
714 715 716 717 718 719 720 721 722 723
//  fbo.release();
//
//  QRect blitRect(0,0,glstate_->viewport_width(),glstate_->viewport_height());
//
//  //
//  //QTime time;
//  //time.restart();
//  QGLFramebufferObject::blitFramebuffer( 0 , blitRect, &fbo, blitRect , GL_COLOR_BUFFER_BIT );
//  //std::cerr << "Elapsed for blit: " << time.elapsed() << std::endl;

Jan Möbius's avatar
 
Jan Möbius committed
724
  glFinish();
Jan Möbius's avatar
Jan Möbius committed
725

Jan Möbius's avatar
 
Jan Möbius committed
726
  frame_time_ = timer.elapsed();
Jan Möbius's avatar
Jan Möbius committed
727

728 729 730
  
  // Inside the glWidget rendering, the system should not send extra updates
  properties_.blockSignals(false);
Jan Möbius's avatar
Jan Möbius committed
731

Jan Möbius's avatar
 
Jan Möbius committed
732 733 734 735 736 737
}


//-----------------------------------------------------------------------------


Jan Möbius's avatar
 
Jan Möbius committed
738
void glViewer::drawScene_mono()
Jan Möbius's avatar
 
Jan Möbius committed
739
{
740 741 742 743
  if (sceneGraphRoot_) {
    ViewObjectMarker *oM = properties_.objectMarker();
    GLuint refBits = 0;
    QSet<GLuint> references;
744

745 746 747
    if (oM)
    {
      glClear (GL_STENCIL_BUFFER_BIT);
748
      ACG::GLState::enable (GL_STENCIL_TEST);
749 750
      glStencilOp (GL_KEEP, GL_KEEP, GL_ZERO);
      glStencilFunc (GL_ALWAYS, 0, ~0);
751

752 753
      for (PluginFunctions::ObjectIterator o_it(PluginFunctions::ALL_OBJECTS, DATA_ALL) ;
          o_it != PluginFunctions::objectsEnd(); ++o_it)
754
      {
755 756 757 758
        bool ok;
        GLuint ref;

        ok = oM->stencilRefForObject(*o_it, ref);
759

760
        if (ok)
761
        {
762 763 764 765
          o_it->stencilRefNode ()->setReference (ref);
          o_it->stencilRefNode ()->show ();
          refBits |= ref;
          references << ref;
766
        }
767 768
        else
          o_it->stencilRefNode ()->hide ();
769
      }
770 771
    }

Jan Möbius's avatar
Jan Möbius committed
772 773 774
    // First pass
    ACG::SceneGraph::DrawAction pass1( properties_.drawMode(), *glstate_ , false);
    ACG::SceneGraph::traverse_multipass(sceneGraphRoot_, pass1, *glstate_, properties_.drawMode() );
775

Jan Möbius's avatar
Jan Möbius committed
776 777 778
    // Second Pass for Blending operations
    ACG::SceneGraph::DrawAction pass2(properties_.drawMode(), *glstate_, true);
    ACG::SceneGraph::traverse_multipass(sceneGraphRoot_, pass2, *glstate_, properties_.drawMode());
Jan Möbius's avatar
 
Jan Möbius committed
779

780 781 782
    if (oM)
    {
      if (oM->type() == ViewObjectMarker::PerBit)
Jan Möbius's avatar
 
Jan Möbius committed
783
      {
784 785 786 787
        references.clear ();
        for (unsigned int i = 0; i < sizeof (GLuint) * 8; i++)
          if (refBits & (1 << i))
            references << (1 << i);
Jan Möbius's avatar
 
Jan Möbius committed
788
      }
789

790
      glPushAttrib(GL_ALL_ATTRIB_BITS);
791

792
      ACG::GLState::enable(GL_BLEND);
793 794 795
      ACG::GLState::disable(GL_DEPTH_TEST);
      ACG::GLState::disable(GL_LIGHTING);
      ACG::GLState::disable(GL_DITHER);
796

797 798
      int vp_l, vp_b, vp_w, vp_h;
      glstate_->get_viewport (vp_l, vp_b, vp_w, vp_h);
799

800 801 802 803 804 805 806
      glMatrixMode(GL_PROJECTION);
      glPushMatrix ();
      glLoadIdentity();
      glOrtho(0, vp_w, vp_h, 0, 0, 1.0);
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix ();
      glLoadIdentity();
807

808
      glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
809

810 811 812 813 814 815 816
      foreach (unsigned int ref, references)
      {
        bool ok;
        GLenum sfactor;
        GLenum dfactor;
        ACG::Vec4f color;
        unsigned int mask = ~0;
817

818
        if (oM->type() == ViewObjectMarker::PerBit)
819
        {
820 821
          ok = oM->blendForStencilRefBit (ref, sfactor, dfactor, color);
          mask = ref;
822
        }
823 824
        else
          ok = oM->blendForStencilRefNumber (ref, sfactor, dfactor, color);
825

826 827
        if (!ok)
          continue;
828

829
        glStencilFunc (GL_EQUAL, ref, mask);
Jan Möbius's avatar
 
Jan Möbius committed
830

831
        ACG::GLState::blendFunc (sfactor, dfactor);
832
        glColor4f (color[0], color [1], color [2], color[3]);
Jan Möbius's avatar
 
Jan Möbius committed
833

834 835 836 837 838 839 840 841
        glBegin (GL_QUADS);
        glVertex2i(0, 0);
        glVertex2i(0, vp_h);
        glVertex2i(vp_w, vp_h);
        glVertex2i(vp_w, 0);
        glEnd ();

      }
Jan Möbius's avatar
 
Jan Möbius committed
842

843 844 845 846
      glMatrixMode(GL_PROJECTION);
      glPopMatrix ();
      glMatrixMode(GL_MODELVIEW);
      glPopMatrix ();
Jan Möbius's avatar
 
Jan Möbius committed
847

848
      glPopAttrib ();
849
      ACG::GLState::disable (GL_STENCIL_TEST);
Jan Möbius's avatar
 
Jan Möbius committed
850
    }
851 852


Jan Möbius's avatar
 
Jan Möbius committed
853
  }
Jan Möbius's avatar
Jan Möbius committed
854

855
  if (properties_.cursorPainter() && properties_.cursorPainter()->enabled () && properties_.cursorPositionValid() )
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
856 857 858 859 860
  {
    glstate_->push_modelview_matrix ();
    // reset view transformation
    glstate_->reset_modelview ();
    // translate cursor position to 0,0
861
    glstate_->translate ( properties_.cursorPoint3D() );
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
862
    // paint cursor
863
    properties_.cursorPainter()->paintCursor (glstate_);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
864 865
    glstate_->pop_modelview_matrix ();
  }
866

Jan Möbius's avatar
 
Jan Möbius committed
867 868
}

Jan Möbius's avatar
 
Jan Möbius committed
869
void glViewer::setHome()
Jan Möbius's avatar
 
Jan Möbius committed
870 871 872
{
  home_modelview_          = glstate_->modelview();
  home_inverse_modelview_  = glstate_->inverse_modelview();
873
  homeOrthoWidth_          = properties_.orthoWidth();
874 875
  home_center_             = properties_.trackballCenter();
  home_radius_             = properties_.trackballRadius();
Jan Möbius's avatar
 
Jan Möbius committed
876 877 878
}


Jan Möbius's avatar
 
Jan Möbius committed
879
void glViewer::home()
Jan Möbius's avatar
 
Jan Möbius committed
880 881 882
{
  makeCurrent();
  glstate_->set_modelview(home_modelview_, home_inverse_modelview_);
883
  properties_.orthoWidth( homeOrthoWidth_ );
884 885
  properties_.trackballCenter( home_center_ );
  properties_.trackballRadius(home_radius_);
Jan Möbius's avatar
 
Jan Möbius committed
886 887
  updateProjectionMatrix();
  updateGL();
888

889
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
890 891 892 893 894

}

//-----------------------------------------------------------------------------

Jan Möbius's avatar
 
Jan Möbius committed
895
void glViewer::viewAll()
Jan Möbius's avatar
 
Jan Möbius committed
896
{
897
  makeCurrent();
Jan Möbius's avatar
 
Jan Möbius committed
898

899 900
  // update scene graph (get new bounding box and set projection right, including near and far plane)
  properties_.lockUpdate();
Jan Möbius's avatar
 
Jan Möbius committed
901

902 903 904
  // move center (in camera coords) to origin and translate in -z dir
  translate(-(glstate_->modelview().transform_point(properties_.sceneCenter()))
            - ACG::Vec3d(0.0, 0.0, 3.0 * properties_.sceneRadius()));
905

906 907 908 909
  properties_.orthoWidth( 1.1 * properties_.sceneRadius() );
  double aspect = (double) glWidth() / (double) glHeight();
  if (aspect > 1.0)
    properties_.orthoWidth( aspect * properties_.orthoWidth() ) ;
910

Jan Möbius's avatar
Jan Möbius committed
911 912 913 914 915
  unsigned int maxPases = 1;
  ACG::Vec3d bbmin,bbmax;
  ACG::SceneGraph::analyzeSceneGraph(PluginFunctions::getSceneGraphRootNode(),maxPases,bbmin,bbmax);

  sceneGraph ( PluginFunctions::getSceneGraphRootNode(), maxPases,bbmin,bbmax,true);
916

917 918 919
  properties_.unLockUpdate();
  updateProjectionMatrix();
  updateGL();
920

921
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
922 923 924 925 926 927 928

}


//-----------------------------------------------------------------------------


Jan Möbius's avatar
 
Jan Möbius committed
929
void glViewer::setView(const ACG::GLMatrixd& _modelview,
Jan Möbius's avatar
 
Jan Möbius committed
930 931 932 933 934
			                  const ACG::GLMatrixd& _inverse_modelview)
{
  makeCurrent();
  glstate_->set_modelview(_modelview, _inverse_modelview);
  updateGL();
935

936
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
937 938 939 940 941 942
}


//-----------------------------------------------------------------------------


Jan Möbius's avatar
 
Jan Möbius committed
943
void glViewer::initializeGL()
Jan Möbius's avatar
 
Jan Möbius committed
944 945 946
{

  // lock update
947
  properties_.lockUpdate();
Jan Möbius's avatar
 
Jan Möbius committed
948 949 950 951 952

  // init GL state
  glstate_->initialize();

  // OpenGL state
953 954
  ACG::GLState::enable(GL_DEPTH_TEST);
  ACG::GLState::enable(GL_LIGHTING);
955
  ACG::GLState::disable(GL_DITHER);
956
  ACG::GLState::shadeModel( GL_FLAT );
Jan Möbius's avatar
 
Jan Möbius committed
957 958 959 960 961


  projectionMode(   projectionMode_   );
  normalsMode(      normalsMode_      );

962
  // Update all settings which would require a redraw
963
  applyProperties();
Jan Möbius's avatar
 
Jan Möbius committed
964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981

  // modelview
  glstate_->translate(0.0, 0.0, -3.0);
  setHome();


  // pixel transfer
  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
  glPixelStorei(GL_PACK_ALIGNMENT, 1);


  // unlock update (we started locked)
982
  properties_.unLockUpdate();
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
983

984 985 986 987
  initialized_ = true;

  if (sceneGraphRoot_)
  {
Jan Möbius's avatar
Jan Möbius committed
988 989 990 991 992 993 994
    unsigned int maxPases = 1;
    ACG::Vec3d bbmin,bbmax;
    ACG::SceneGraph::analyzeSceneGraph(sceneGraphRoot_,maxPases,bbmin,bbmax);

    sceneGraph ( sceneGraphRoot_, maxPases,bbmin,bbmax,true);

    viewAll();
995
  }
Jan Möbius's avatar
 
Jan Möbius committed
996 997 998 999 1000 1001
}


//-----------------------------------------------------------------------------


Jan Möbius's avatar
 
Jan Möbius committed
1002
void glViewer::paintGL()
Jan Möbius's avatar
 
Jan Möbius committed
1003
{
1004 1005
  if (!initialized_)
    initializeGL ();
Jan Möbius's avatar
 
Jan Möbius committed
1006

1007
  if (!properties_.updateLocked())
Jan Möbius's avatar
 
Jan Möbius committed
1008
  {
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
1009 1010
    ACG::Vec4f clear_color;

1011
    properties_.lockUpdate();
Jan Möbius's avatar
 
Jan Möbius committed
1012 1013 1014

    glPushAttrib (GL_ALL_ATTRIB_BITS);

1015 1016
    ACG::GLState::enable(GL_DEPTH_TEST);
    ACG::GLState::enable(GL_LIGHTING);