QtBaseViewer.cc 72.1 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
  // Clear back buffer here:
  // Render plugins do not have to worry about using scissor test for clearing their viewports later on.
630 631
  glClearColor(properties_.backgroundColor()[0], properties_.backgroundColor()[1],
		  properties_.backgroundColor()[2], properties_.backgroundColor()[3]);
632 633 634 635 636 637 638
  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
639

640
  // Check if we use build in default renderer
Jan Möbius's avatar
Jan Möbius committed
641
  if ( renderManager().activeId( properties_.viewerId() ) == 0 ) {
642
    drawScene_mono();
Jan Möbius's avatar
Jan Möbius committed
643
  } else {
644 645 646 647 648 649 650 651 652
    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
653
  }
654
  checkGLError();
Jan Möbius's avatar
Jan Möbius committed
655 656


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


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

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


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

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

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

677 678 679 680
    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
681

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

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

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

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

693 694 695 696
      // 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
697 698


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

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

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

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

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

Jan Möbius's avatar
Jan Möbius committed
715 716 717 718 719 720 721 722 723 724
//  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
725
  glFinish();
Jan Möbius's avatar
Jan Möbius committed
726

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

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

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


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


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

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

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

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

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

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

Jan Möbius's avatar
Jan Möbius committed
777 778 779
    // 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
780

781 782 783
    if (oM)
    {
      if (oM->type() == ViewObjectMarker::PerBit)
Jan Möbius's avatar
 
Jan Möbius committed
784
      {
785 786 787 788
        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
789
      }
790

791
      glPushAttrib(GL_ALL_ATTRIB_BITS);
792

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

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

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

809
      glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
810

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

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

827 828
        if (!ok)
          continue;
829

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

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

835 836 837 838 839 840 841 842
        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
843

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

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


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

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

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

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


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

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

}

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

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

900 901
  // 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
902

903 904 905
  // 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()));
906

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

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

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

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

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

}


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


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

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


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


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

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

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

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


  projectionMode(   projectionMode_   );
  normalsMode(      normalsMode_      );

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

  // 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)
983
  properties_.unLockUpdate();
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
984

985 986 987 988
  initialized_ = true;

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

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

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


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


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

1008
  if (!properties_.updateLocked())
Jan Möbius's avatar
 
Jan Möbius committed
1009
  {
1010
    properties_.lockUpdate();
Jan Möbius's avatar
 
Jan Möbius committed
1011 1012 1013

    glPushAttrib (GL_ALL_ATTRIB_BITS);

1014 </