QtBaseViewer.cc 75.7 KB
Newer Older
Jan Möbius's avatar
Jan Möbius committed
1 2 3
/*===========================================================================*\
*                                                                            *
*                              OpenFlipper                                   *
Martin Schultz's avatar
Martin Schultz committed
4 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 33 34 35 36 37 38
 *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
 *           Department of Computer Graphics and Multimedia                  *
 *                          All rights reserved.                             *
 *                            www.openflipper.org                            *
 *                                                                           *
 *---------------------------------------------------------------------------*
 * This file is part of OpenFlipper.                                         *
 *---------------------------------------------------------------------------*
 *                                                                           *
 * Redistribution and use in source and binary forms, with or without        *
 * modification, are permitted provided that the following conditions        *
 * are met:                                                                  *
 *                                                                           *
 * 1. Redistributions of source code must retain the above copyright notice, *
 *    this list of conditions and the following disclaimer.                  *
 *                                                                           *
 * 2. Redistributions in binary form must reproduce the above copyright      *
 *    notice, this list of conditions and the following disclaimer in the    *
 *    documentation and/or other materials provided with the distribution.   *
 *                                                                           *
 * 3. Neither the name of the copyright holder nor the names of its          *
 *    contributors may be used to endorse or promote products derived from   *
 *    this software without specific prior written permission.               *
 *                                                                           *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       *
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           *
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  *
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       *
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        *
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    *
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      *
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              *
Jan Möbius's avatar
Jan Möbius committed
39
*                                                                            *
40 41
\*===========================================================================*/

42

Jan Möbius's avatar
 
Jan Möbius committed
43 44 45 46 47 48




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


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

Christopher Tenter's avatar
Christopher Tenter committed
56 57
#include <ACG/GL/acg_glew.hh>

Jan Möbius's avatar
 
Jan Möbius committed
58
#include "QtBaseViewer.hh"
Jan Möbius's avatar
Jan Möbius committed
59
#include "QtGLViewerLayout.hh"
Christopher Tenter's avatar
Christopher Tenter committed
60
#include "PostProcessing.hh"
Jan Möbius's avatar
Jan Möbius committed
61

Jan Möbius's avatar
 
Jan Möbius committed
62
#include <ACG/QtWidgets/QtWheel.hh>
63
#include <ACG/Scenegraph/CoordsysNode.hh>
Jan Möbius's avatar
Jan Möbius committed
64
#include <ACG/Scenegraph/SceneGraphAnalysis.hh>
65
#include <ACG/Scenegraph/StencilRefNode.hh>
66
#include <ACG/GL/GLError.hh>
67
#include <ACG/GL/IRenderer.hh>
Jan Möbius's avatar
 
Jan Möbius committed
68

Martin Schultz's avatar
Martin Schultz committed
69 70
#include <QGraphicsWidget>
#include <QString>
Hans-Christian Ebke's avatar
Hans-Christian Ebke committed
71 72 73 74 75 76
#include <QBoxLayout>
#include <QtNetwork/QUdpSocket>
#include <QToolBar>
#include <QGraphicsSceneDragDropEvent>
#include <QPropertyAnimation>

Jan Möbius's avatar
 
Jan Möbius committed
77 78 79 80 81 82 83
#include <QMimeData>

#include <QClipboard>
#include <QApplication>
#include <QSplitter>
#include <QColorDialog>

84
#include <QGraphicsView>
Jan Möbius's avatar
 
Jan Möbius committed
85 86
#include <QGraphicsProxyWidget>

87 88
#include <QImageWriter>

89

90
#include <QOpenGLFramebufferObject>
91

Jan Möbius's avatar
 
Jan Möbius committed
92 93 94 95 96 97 98 99
#ifdef max
#  undef max
#endif

#ifdef min
#  undef min
#endif

100
#include <OpenFlipper/BasePlugin/PluginFunctions.hh>
Jan Möbius's avatar
Jan Möbius committed
101
#include <OpenFlipper/common/ViewObjectMarker.hh>
Jan Möbius's avatar
 
Jan Möbius committed
102

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

105
#include <OpenFlipper/common/RendererInfo.hh>
106
#include <QOpenGLWidget>
107

Jan Möbius's avatar
 
Jan Möbius committed
108 109 110 111 112 113
//== NAMESPACES ===============================================================



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

114
static const char          COPY_PASTE_VIEW_START_STRING[] =
Jan Möbius's avatar
 
Jan Möbius committed
115 116 117 118 119
  "ACG::QtWidgets::QGLViewerWidget encoded view";

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


120
glViewer::glViewer( QGraphicsScene* _scene,
121
                    OFGLWidget* _glWidget,
122
                    Viewer::ViewerProperties& _properties,
123
                    QGraphicsWidget* _parent) :
Jan Möbius's avatar
 
Jan Möbius committed
124
  QGraphicsWidget(_parent),
Jan Möbius's avatar
 
Jan Möbius committed
125 126
  glareaGrabbed_(false),
  projectionUpdateLocked_(false),
Jan Möbius's avatar
 
Jan Möbius committed
127 128
  glScene_(_scene),
  glWidget_(_glWidget),
129
  glDebugLogger_(0),
Jan Möbius's avatar
Jan Möbius committed
130
  pickCache_(0),
131
  mouseCache_(nullptr),
Jan Möbius's avatar
Jan Möbius committed
132 133
  updatePickCache_(true),
  pickCacheSupported_(true),
134
  constrainedRotationAxis_(std::numeric_limits<double>::quiet_NaN(), 0, 0),
135
  clickEvent_(QEvent::MouseButtonPress, QPoint (), Qt::NoButton, Qt::NoButton, Qt::NoModifier),
Dirk Wilden's avatar
Dirk Wilden committed
136
  properties_(_properties),
137
  glstate_(0),
Jan Möbius's avatar
Jan Möbius committed
138 139 140 141 142
  initialized_(false),
  flyAnimationPerspective_(0),
  flyAnimationOrthogonal_(0),
  flyAngle_(0.0),
  currentAnimationPos_(0.0),
Christopher Tenter's avatar
Christopher Tenter committed
143 144
  flyMoveBack_(false),
  postproc_(0)
Jan Möbius's avatar
 
Jan Möbius committed
145 146 147
{

  // widget stuff
148
  createWidgets();
Jan Möbius's avatar
 
Jan Möbius committed
149 150

  // bind GL context to GL state class
151
  glstate_ = new ACG::GLState(true, _glWidget->format().profile() != OFGLFormat::CoreProfile);
152

153 154
  properties_.setglState( glstate_ );

Jan Möbius's avatar
 
Jan Möbius committed
155 156
  // state
  isRotating_       = false;
Mike Kremer's avatar
Mike Kremer committed
157
  lookAround_       = false;
Jan Möbius's avatar
 
Jan Möbius committed
158 159 160

  sceneGraphRoot_   = 0;

161
  normalsMode_      = NORMALIZE_NORMALS;
Jan Möbius's avatar
 
Jan Möbius committed
162
  projectionMode_   = PERSPECTIVE_PROJECTION;
Jan Möbius's avatar
Jan Möbius committed
163
  navigationMode_   = NORMAL_NAVIGATION;
164

Jan Möbius's avatar
 
Jan Möbius committed
165 166 167 168 169 170 171 172 173 174 175 176
  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 );

Jan's avatar
Jan committed
177
  redrawTime_.start();
Jan Möbius's avatar
 
Jan Möbius committed
178

179 180 181 182
  // timer for animation
  timer_ = new QTimer( this );
  connect( timer_, SIGNAL(timeout()), this, SLOT( slotAnimation()) );

183 184
  fovyModifier_ = 1.0;

185 186 187
  allowRotation_ = true;


Jan Möbius's avatar
 
Jan Möbius committed
188 189 190
  connect( &properties_,SIGNAL(updated()), this, SLOT( slotPropertiesUpdated() ) );


Dirk Wilden's avatar
Dirk Wilden committed
191 192 193
  //check for updated properties once
  slotPropertiesUpdated();

Jan Möbius's avatar
 
Jan Möbius committed
194
  setAcceptDrops(true);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
195

196
  setHome();
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
197

198 199
  clickTimer_.setSingleShot (true);
  connect (&clickTimer_, SIGNAL(timeout ()), this, SLOT(slotClickTimeout ()));
Jan Möbius's avatar
 
Jan Möbius committed
200 201 202 203 204 205
}


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


Jan Möbius's avatar
 
Jan Möbius committed
206
glViewer::~glViewer()
Jan Möbius's avatar
 
Jan Möbius committed
207 208
{
  delete glstate_;
209 210

  deleteGLDebugLogger();
211 212
  if (mouseCache_ != nullptr)
      deleteQFBO(mouseCache_);
Jan Möbius's avatar
 
Jan Möbius committed
213 214 215 216 217 218
}


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


219 220 221 222 223
//QSizeF
//glViewer::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const
//{
//  return QSizeF( 600, 600 );
//}
Jan Möbius's avatar
 
Jan Möbius committed
224 225 226 227

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


Jan Möbius's avatar
 
Jan Möbius committed
228
void glViewer::makeCurrent() {
229

230
  const GLuint prevFbo = ACG::GLState::getFramebufferDraw();
231
  const GLuint prevReadFbo = ACG::GLState::getFramebufferRead();
232

233 234

  // calling makeCurrent binds the default FBO when QOpenGLWidget is used
235
  makeWidgetCurrent();
236 237 238

  //restore the previously bound FBO, if it was not 0 as Qt Documentation says we shall not bind 0
  if(prevFbo != 0)
239 240 241
    ACG::GLState::bindFramebuffer(GL_DRAW_FRAMEBUFFER, prevFbo);
  if(prevReadFbo != 0)
      ACG::GLState::bindFramebuffer(GL_READ_FRAMEBUFFER, prevFbo);
242

Jan Möbius's avatar
 
Jan Möbius committed
243 244 245 246 247
}


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

Jan Möbius's avatar
Jan Möbius committed
248 249 250 251 252
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
253 254 255
{
  sceneGraphRoot_ = _root;

Jan Möbius's avatar
Jan Möbius committed
256
  if (sceneGraphRoot_ )
Jan Möbius's avatar
 
Jan Möbius committed
257 258
  {

Jan Möbius's avatar
Jan Möbius committed
259 260
    // set max number of render pass
    glstate_->set_max_render_passes(_maxPasses);
Jan Möbius's avatar
Jan Möbius committed
261
    
Jan Möbius's avatar
Jan Möbius committed
262 263 264
    if ( ( _bbmin[0] > _bbmax[0] ) ||
         ( _bbmin[1] > _bbmax[1] ) ||
         ( _bbmin[2] > _bbmax[2] )   ) {
265 266
      
      // Invalid bounding box, try to recover
267
      setScenePos( properties_.sceneCenter() , properties_.sceneRadius(), _resetTrackBall );
268 269
    
      // Update bounding box to match the scene geometry after recovery
Jan Möbius's avatar
Jan Möbius committed
270 271
      _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
272 273
    } else {
      
274
      // For very small scenes, we set the scene radius to 0.1
Jan Möbius's avatar
Jan Möbius committed
275
      // otherwise we take the real radius
Jan Möbius's avatar
Jan Möbius committed
276 277
      if ( ( _bbmax - _bbmin ).max() < OpenFlipperSettings().value("Core/Gui/glViewer/minimalSceneSize",0.1).toDouble() )  {
        setScenePos( ( _bbmin + _bbmax )        * 0.5,
278
                     OpenFlipperSettings().value("Core/Gui/glViewer/minimalSceneSize",0.1).toDouble(),
Jan Möbius's avatar
Jan Möbius committed
279 280 281
                     _resetTrackBall);
                   
      } else {
Jan Möbius's avatar
Jan Möbius committed
282 283
        setScenePos( ( _bbmin + _bbmax )        * 0.5,
                     ( _bbmax - _bbmin ).norm() * 0.5,
Jan Möbius's avatar
Jan Möbius committed
284 285 286 287
                     _resetTrackBall); 
      }
                   
    }
288 289
                   
    // remember the new bounding box for the state
Jan Möbius's avatar
Jan Möbius committed
290
    glstate_->set_bounding_box(_bbmin,_bbmax);
291
    
Jan Möbius's avatar
 
Jan Möbius committed
292
  }
293
  
Jan Möbius's avatar
 
Jan Möbius committed
294 295 296 297 298 299 300 301 302 303

  updateGL();

  emit(signalSceneGraphChanged(sceneGraphRoot_));
}


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


Jan Möbius's avatar
 
Jan Möbius committed
304
void glViewer::trackMouse(bool _track)
Jan Möbius's avatar
 
Jan Möbius committed
305 306 307 308 309 310 311
{
  trackMouse_ = _track;
}


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

312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
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
332
void glViewer::perspectiveProjection()
Jan Möbius's avatar
 
Jan Möbius committed
333 334 335 336 337 338
{
  projectionMode(PERSPECTIVE_PROJECTION);
  updateGL();
}


Jan Möbius's avatar
 
Jan Möbius committed
339
void glViewer::orthographicProjection()
Jan Möbius's avatar
 
Jan Möbius committed
340 341 342 343 344 345
{
  projectionMode(ORTHOGRAPHIC_PROJECTION);
  updateGL();
}


Jan Möbius's avatar
 
Jan Möbius committed
346
void glViewer::toggleProjectionMode()
Jan Möbius's avatar
 
Jan Möbius committed
347 348 349 350 351 352 353 354 355 356
{
  if (projectionMode_ == ORTHOGRAPHIC_PROJECTION)
    projectionMode(PERSPECTIVE_PROJECTION);
  else
    projectionMode(ORTHOGRAPHIC_PROJECTION);

  updateGL();
}


Jan Möbius's avatar
 
Jan Möbius committed
357
void glViewer::projectionMode(ProjectionMode _p)
Jan Möbius's avatar
 
Jan Möbius committed
358 359
{
  if ((projectionMode_ = _p) == ORTHOGRAPHIC_PROJECTION)
360
    emit projectionModeChanged( true );
Jan Möbius's avatar
 
Jan Möbius committed
361
  else
362
    emit projectionModeChanged( false );
Jan Möbius's avatar
 
Jan Möbius committed
363 364

  updateProjectionMatrix();
365

366 367
  setCoordSysProjection(_p);

368
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
369 370
}

371 372 373
void glViewer::toggleNavigationMode()
{
  if (navigationMode_ == NORMAL_NAVIGATION)
Mike Kremer's avatar
Mike Kremer committed
374
    navigationMode(FIRSTPERSON_NAVIGATION);
375 376 377 378 379 380 381 382 383 384 385 386 387
  else
    navigationMode(NORMAL_NAVIGATION);
}


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

388 389 390 391 392 393 394 395 396 397 398
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();
}

399
void glViewer::updateProjectionMatrix(double _aspect)
Jan Möbius's avatar
 
Jan Möbius committed
400 401 402 403 404 405 406 407
{
  if( projectionUpdateLocked_ )
    return;

  makeCurrent();

  glstate_->reset_projection();

408
  const double aspect = _aspect ? _aspect : this->aspect_ratio();
409
  // In stereo mode we have to use a perspective matrix
410
  if ( projectionMode_ == PERSPECTIVE_PROJECTION)
Jan Möbius's avatar
 
Jan Möbius committed
411
  {
412

413
    // Get fovy
414
    const double fovy = this->field_of_view_vertical();
415 416

    glstate_->perspective(fovy, (GLdouble) aspect,
417
                          near_plane(), far_plane());
Jan Möbius's avatar
Jan Möbius committed
418 419 420
  }
  else
  {
Jan Möbius's avatar
 
Jan Möbius committed
421

422 423 424
    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
425
  }
426

Jan Möbius's avatar
 
Jan Möbius committed
427 428 429 430 431 432
}


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


433
void glViewer::setScenePos(const ACG::Vec3d& _center, double _radius, const bool _resetTrackBall)
Jan Möbius's avatar
 
Jan Möbius committed
434
{
435
  if(_resetTrackBall) {
436
    properties_.trackballCenter(_center);
437 438
  }

439
  properties_.sceneCenter(_center);
440

441 442
  properties_.sceneRadius(_radius);
  properties_.trackballRadius(_radius);
443

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

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

   // Safety check, if near < 0
Jan Möbius's avatar
Jan Möbius committed
450
   if ( nearPlane <= 0.0 ) {
451
     std::cerr << "Error in BaseViewer drawScene, nearplane <= 0.0" << std::endl;
Jan Möbius's avatar
Jan Möbius committed
452
     nearPlane = 0.000000000000001;
453 454 455
   }

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

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

463 464 465 466
  updateProjectionMatrix();
  updateGL();

  emit viewChanged();
467 468 469 470 471 472
}


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


Jan Möbius's avatar
 
Jan Möbius committed
473
void glViewer::viewingDirection( const ACG::Vec3d& _dir, const ACG::Vec3d& _up )
Jan Möbius's avatar
 
Jan Möbius committed
474 475
{
  // calc eye point for this direction
476
  ACG::Vec3d eye = properties_.sceneCenter() - _dir * ( 3.0 * properties_.sceneRadius());
Jan Möbius's avatar
 
Jan Möbius committed
477 478

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

481
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
482 483
}

484 485 486 487 488 489 490
//-----------------------------------------------------------------------------

void glViewer::lookAt(const ACG::Vec3d& _eye, const ACG::Vec3d& _center, const ACG::Vec3d& _up) {
    
    glstate_->reset_modelview();
    glstate_->lookAt(_eye, _center, _up);
    
491 492
    properties_.sceneCenter( _center );
    properties_.sceneRadius( (properties_.sceneCenter() - _eye).norm() );
493 494 495
    
    emit viewChanged();
}
Jan Möbius's avatar
 
Jan Möbius committed
496 497 498

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

Jan Möbius's avatar
 
Jan Möbius committed
499
void glViewer::normalsMode(NormalsMode _mode)
Jan Möbius's avatar
 
Jan Möbius committed
500
{
501
  if (glstate_->compatibilityProfile())
Jan Möbius's avatar
 
Jan Möbius committed
502
  {
503 504 505 506
    makeCurrent();

    switch (normalsMode_ = _mode)
    {
Jan Möbius's avatar
 
Jan Möbius committed
507
    case DONT_TOUCH_NORMALS:
508
      ACG::GLState::disable(GL_NORMALIZE);
Jan Möbius's avatar
 
Jan Möbius committed
509 510 511
      break;

    case NORMALIZE_NORMALS:
512
      ACG::GLState::enable(GL_NORMALIZE);
Jan Möbius's avatar
 
Jan Möbius committed
513
      break;
514
    }
Jan Möbius's avatar
 
Jan Möbius committed
515

516 517
    updateGL();
  }
Jan Möbius's avatar
 
Jan Möbius committed
518 519 520 521 522 523
}


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


Jan Möbius's avatar
 
Jan Möbius committed
524
void glViewer::updateGL()
Jan Möbius's avatar
 
Jan Möbius committed
525
{
Jan Möbius's avatar
 
Jan Möbius committed
526
  if (!properties_.updateLocked() && isVisible() )
Jan Möbius's avatar
 
Jan Möbius committed
527
  {
Jan Möbius's avatar
Jan Möbius committed
528
    updatePickCache_ = true;
Jan Möbius's avatar
 
Jan Möbius committed
529
    update();
530 531

    emit viewUpdated();
Jan Möbius's avatar
 
Jan Möbius committed
532 533 534 535 536 537 538 539
  }
}



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


540
void glViewer::drawScene(double _aspect)
Jan Möbius's avatar
 
Jan Möbius committed
541
{
542 543 544 545
  
  // Inside the glWidget rendering, the system should not send extra updates
  properties_.blockSignals(true);
  
Jan's avatar
Jan committed
546
  QElapsedTimer  timer;
Jan Möbius's avatar
 
Jan Möbius committed
547 548
  timer.start();

Jan Möbius's avatar
 
Jan Möbius committed
549 550 551 552
  // *****************************************************************
  // Adjust clipping planes
  // *****************************************************************
  // Far plane
553
  ACG::Vec3d c = glstate_->modelview().transform_point(properties_.sceneCenter());
Jan Möbius's avatar
 
Jan Möbius committed
554

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

  // Safety check, if near < 0
Jan Möbius's avatar
Jan Möbius committed
559
  if ( nearPlane <= 0.0 ) {
560
    std::cerr << "Error in BaseViewer drawScene, nearplane < 0" << std::endl;
Jan Möbius's avatar
Jan Möbius committed
561
    nearPlane = 0.000000000000001;
562 563 564
  }

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

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

572
  updateProjectionMatrix(_aspect);
Jan Möbius's avatar
 
Jan Möbius committed
573 574 575 576 577

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

  makeCurrent();
578 579
  if(!glstate_->compatibilityProfile())
    defaultVAO_.bind();
580

Jan Möbius's avatar
Jan Möbius committed
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
  // 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 {
//
//  }

602 603 604 605 606 607 608
  // save hardware backbuffer
  GLuint backbufferFbo = 0;
  GLuint backbufferTarget = 0;
  glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&backbufferFbo);
  glGetIntegerv(GL_DRAW_BUFFER, (GLint*)&backbufferTarget);


Christopher Tenter's avatar
Christopher Tenter committed
609

610
  // Render plugins do not have to worry about using scissor test for clearing their viewports later on.
611
  glClearColor(properties_.backgroundColor()[0], properties_.backgroundColor()[1],
Christopher Tenter's avatar
Christopher Tenter committed
612
    properties_.backgroundColor()[2], properties_.backgroundColor()[3]);
613 614 615 616 617 618 619
  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
620

Christopher Tenter's avatar
Christopher Tenter committed
621 622 623 624 625

  // setup scene target fbo
  if (!postproc_)
    postproc_ = new PostProcessing();

Christopher Tenter's avatar
Christopher Tenter committed
626 627 628 629
  const int numPostProcessors = postProcessorManager().numActive(properties_.viewerId());

  bool stereoOpenGL = false;
  bool stereoAnaglyph = false;
630 631 632
  ACG::GLMatrixd projSave = glstate_->projection();
  ACG::GLMatrixd projLR[2];

Christopher Tenter's avatar
Christopher Tenter committed
633 634 635
  if (properties_.stereo()) {
    stereoOpenGL = OpenFlipper::Options::stereoMode () == OpenFlipper::Options::OpenGL && OpenFlipper::Options::glStereo ();
    stereoAnaglyph = !stereoOpenGL;
636
    computeProjStereo(glstate_->viewport_width(), glstate_->viewport_height(), properties_, projLR, projLR+1);
Christopher Tenter's avatar
Christopher Tenter committed
637 638
  }

Christopher Tenter's avatar
Christopher Tenter committed
639 640 641 642 643 644 645 646 647
  if (!stereoOpenGL && !stereoAnaglyph)
  {
    // setup render target fbo
    postproc_->setupScene(properties_.viewerId(), glstate_->viewport_width(), glstate_->viewport_height(),
      properties_.multisampling() ? 16 : 0, -1);
  }



648
  // Check if we use build in default renderer
Jan Möbius's avatar
Jan Möbius committed
649
  if ( renderManager().activeId( properties_.viewerId() ) == 0 ) {
650
    drawScene_mono();
Jan Möbius's avatar
Jan Möbius committed
651
  } else {
652 653 654 655 656 657
    RenderInterface* renderPlugin = renderManager().active( properties_.viewerId() )->plugin;

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

    if (shaderRenderPlugin)
658
    {
659
      shaderRenderPlugin->setViewerID( properties_.viewerId() );
660 661
      shaderRenderPlugin->setCoreProfileMode( OpenFlipper::Options::coreProfile() );
    }
662

Christopher Tenter's avatar
Christopher Tenter committed
663
    if (stereoOpenGL || stereoAnaglyph) {
Christopher Tenter's avatar
Christopher Tenter committed
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679
      // save current fbo
      GLuint backbufferFbo = 0;
      GLuint backbufferTarget = 0;
      glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint*)&backbufferFbo);
      glGetIntegerv(GL_DRAW_BUFFER, (GLint*)&backbufferTarget);

      // setup stereo rendering

      // left eye: fbo 0
      // right eye: fbo 1

      for (int eye = 0; eye < 2; ++eye) {
        glstate_->set_projection(projLR[eye]);
        if (stereoOpenGL && !numPostProcessors) {
          // render directly into back_left
          glDrawBuffer(eye ? GL_BACK_RIGHT : GL_BACK_LEFT);
Christopher Tenter's avatar
Christopher Tenter committed
680 681 682
          glEnable(GL_SCISSOR_TEST);
          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
          glDisable(GL_SCISSOR_TEST);
Christopher Tenter's avatar
Christopher Tenter committed
683 684
        }
        else {
Christopher Tenter's avatar
Christopher Tenter committed
685 686
          postproc_->setupScene(properties_.viewerId(), glstate_->viewport_width(), glstate_->viewport_height(),
            properties_.multisampling() ? 16 : 0, eye);
Christopher Tenter's avatar
Christopher Tenter committed
687
        }
688

Christopher Tenter's avatar
Christopher Tenter committed
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
        renderPlugin->render(glstate_,properties_);
        drawCursor();
      }

      // restore projection
      glstate_->set_projection(projSave);

      // restore backbuffer
      glBindFramebuffer(GL_FRAMEBUFFER, backbufferFbo);
      glDrawBuffer(backbufferTarget);
    }
    else {
      renderPlugin->render(glstate_,properties_);
      drawCursor();
    }
Jan Möbius's avatar
Jan Möbius committed
704
  }
705
  checkGLError();
Jan Möbius's avatar
Jan Möbius committed
706

707 708
  // =================================================================================
  // Post-Processing pipeline
Jan Möbius's avatar
Jan Möbius committed
709 710


Christopher Tenter's avatar
Christopher Tenter committed
711 712 713 714 715 716
  postproc_->postProcess(properties_.viewerId(),
    glstate_,
    glstate_->modelview(),
    (stereoOpenGL || stereoAnaglyph) ? projLR[0] : glstate_->projection(),
    projLR[1],
    stereoOpenGL);
Jan Möbius's avatar
Jan Möbius committed
717

Christopher Tenter's avatar
Christopher Tenter committed
718 719
  if (stereoAnaglyph)
    postproc_->resolveStereoAnyglyph(properties_.viewerId());
Jan Möbius's avatar
Jan Möbius committed
720 721

  // =================================================================================
722
  glBindFramebuffer(GL_FRAMEBUFFER, backbufferFbo);
723
  glDrawBuffer(backbufferTarget);
Jan Möbius's avatar
Jan Möbius committed
724
  // unbind vbo for qt log window
Hans-Christian Ebke's avatar
Hans-Christian Ebke committed
725 726 727
  ACG::GLState::bindBuffer(GL_ARRAY_BUFFER, 0);
  ACG::GLState::activeTexture(GL_TEXTURE0);
  ACG::GLState::bindTexture(GL_TEXTURE_2D, 0);
Jan Möbius's avatar
Jan Möbius committed
728 729 730 731 732 733 734 735 736
//  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
737
  glFinish();
Jan Möbius's avatar
Jan Möbius committed
738

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

741 742 743
  
  // Inside the glWidget rendering, the system should not send extra updates
  properties_.blockSignals(false);
Jan Möbius's avatar
 
Jan Möbius committed
744 745 746 747 748 749
}


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


Jan Möbius's avatar
 
Jan Möbius committed
750
void glViewer::drawScene_mono()
Jan Möbius's avatar
 
Jan Möbius committed
751
{
752 753 754 755
  if (sceneGraphRoot_) {
    ViewObjectMarker *oM = properties_.objectMarker();
    GLuint refBits = 0;
    QSet<GLuint> references;
756

757 758 759
    if (oM)
    {
      glClear (GL_STENCIL_BUFFER_BIT);
760
      ACG::GLState::enable (GL_STENCIL_TEST);
761 762
      glStencilOp (GL_KEEP, GL_KEEP, GL_ZERO);
      glStencilFunc (GL_ALWAYS, 0, ~0);
763

764 765
      for (PluginFunctions::ObjectIterator o_it(PluginFunctions::ALL_OBJECTS, DATA_ALL) ;
          o_it != PluginFunctions::objectsEnd(); ++o_it)
766
      {
767 768 769 770
        bool ok;
        GLuint ref;

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

772
        if (ok)
773
        {
774 775 776 777
          o_it->stencilRefNode ()->setReference (ref);
          o_it->stencilRefNode ()->show ();
          refBits |= ref;
          references << ref;
778
        }
779 780
        else
          o_it->stencilRefNode ()->hide ();
781
      }
782 783
    }

Jan Möbius's avatar
Jan Möbius committed
784 785 786
    // First pass
    ACG::SceneGraph::DrawAction pass1( properties_.drawMode(), *glstate_ , false);
    ACG::SceneGraph::traverse_multipass(sceneGraphRoot_, pass1, *glstate_, properties_.drawMode() );
787

Jan Möbius's avatar
Jan Möbius committed
788 789 790
    // 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
791

792 793 794
    if (oM)
    {
      if (oM->type() == ViewObjectMarker::PerBit)
Jan Möbius's avatar
 
Jan Möbius committed
795
      {
796 797 798 799
        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
800
      }
801

802
      glPushAttrib(GL_ALL_ATTRIB_BITS);
803

804
      ACG::GLState::enable(GL_BLEND);
805
      ACG::GLState::disable(GL_DEPTH_TEST);
806 807 808 809

      if (glstate_->compatibilityProfile())
        ACG::GLState::disable(GL_LIGHTING);

810
      ACG::GLState::disable(GL_DITHER);
811

812 813
      int vp_l, vp_b, vp_w, vp_h;
      glstate_->get_viewport (vp_l, vp_b, vp_w, vp_h);
814

815 816 817 818 819 820 821
      glMatrixMode(GL_PROJECTION);
      glPushMatrix ();
      glLoadIdentity();
      glOrtho(0, vp_w, vp_h, 0, 0, 1.0);
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix ();
      glLoadIdentity();
822

823
      glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
824

825 826 827 828 829 830 831
      foreach (unsigned int ref, references)
      {
        bool ok;
        GLenum sfactor;
        GLenum dfactor;
        ACG::Vec4f color;
        unsigned int mask = ~0;
832

833
        if (oM->type() == ViewObjectMarker::PerBit)
834
        {
835 836
          ok = oM->blendForStencilRefBit (ref, sfactor, dfactor, color);
          mask = ref;
837
        }
838 839
        else
          ok = oM->blendForStencilRefNumber (ref, sfactor, dfactor, color);
840

841 842
        if (!ok)
          continue;
843

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

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

849 850 851 852 853 854 855 856
        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
857

858 859 860 861
      glMatrixMode(GL_PROJECTION);
      glPopMatrix ();
      glMatrixMode(GL_MODELVIEW);
      glPopMatrix ();
Jan Möbius's avatar
 
Jan Möbius committed
862

863
      glPopAttrib ();
864
      ACG::GLState::disable (GL_STENCIL_TEST);
Jan Möbius's avatar
 
Jan Möbius committed
865
    }
866 867


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

Christopher Tenter's avatar
Christopher Tenter committed
870 871 872 873 874 875 876
  drawCursor();

}


void glViewer::drawCursor()
{
877
  if (properties_.cursorPainter() && properties_.cursorPainter()->enabled () && properties_.cursorPositionValid() )
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
878 879 880 881 882
  {
    glstate_->push_modelview_matrix ();
    // reset view transformation
    glstate_->reset_modelview ();
    // translate cursor position to 0,0
883
    glstate_->translate ( properties_.cursorPoint3D() );
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
884
    // paint cursor
885
    properties_.cursorPainter()->paintCursor (glstate_);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
886 887
    glstate_->pop_modelview_matrix ();
  }
Jan Möbius's avatar
 
Jan Möbius committed
888 889
}

Christopher Tenter's avatar
Christopher Tenter committed
890

Jan Möbius's avatar
 
Jan Möbius committed
891
void glViewer::setHome()
Jan Möbius's avatar
 
Jan Möbius committed
892 893 894
{
  home_modelview_          = glstate_->modelview();
  home_inverse_modelview_  = glstate_->inverse_modelview();
895
  homeOrthoWidth_          = properties_.orthoWidth();
896 897
  home_center_             = properties_.trackballCenter();
  home_radius_             = properties_.trackballRadius();
Jan Möbius's avatar
 
Jan Möbius committed
898 899 900
}


Jan Möbius's avatar
 
Jan Möbius committed
901
void glViewer::home()
Jan Möbius's avatar
 
Jan Möbius committed
902 903 904
{
  makeCurrent();
  glstate_->set_modelview(home_modelview_, home_inverse_modelview_);
905
  properties_.orthoWidth( homeOrthoWidth_ );
906 907
  properties_.trackballCenter( home_center_ );
  properties_.trackballRadius(home_radius_);
Jan Möbius's avatar
 
Jan Möbius committed
908 909
  updateProjectionMatrix();
  updateGL();
910

911
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
912 913 914 915 916

}

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

Jan Möbius's avatar
 
Jan Möbius committed
917
void glViewer::viewAll()
Jan Möbius's avatar
 
Jan Möbius committed
918
{
919 920 921
  makeCurrent();
  // 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
922

923 924 925 926 927 928 929 930 931 932
  unsigned int maxPases = 1;
  ACG::Vec3d bbmin,bbmax;
  // update scene bounding boxes
  ACG::SceneGraph::analyzeSceneGraph(PluginFunctions::getSceneGraphRootNode(),maxPases,bbmin,bbmax);

  // update scene properties (near, far plane, scene radius according to the computed bounding boxes)
  sceneGraph ( PluginFunctions::getSceneGraphRootNode(), maxPases,bbmin,bbmax,true);


  // update camera
933 934 935
  // 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()));
936

937 938 939 940
  properties_.orthoWidth( 1.1 * properties_.sceneRadius() );
  double aspect = (double) glWidth() / (double) glHeight();
  if (aspect > 1.0)
    properties_.orthoWidth( aspect * properties_.orthoWidth() ) ;
941

942 943 944
  properties_.unLockUpdate();
  updateProjectionMatrix();
  updateGL();