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-2011 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 64 65 66
#include <ACG/GL/gl.hh>

#include <iostream>
#include <string>
67
#include <cassert>
Jan Möbius's avatar
 
Jan Möbius committed
68 69 70 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

#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>

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

108 109
#include <QImageWriter>

110 111 112 113 114 115 116 117
#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
118 119 120 121 122 123 124 125
#ifdef max
#  undef max
#endif

#ifdef min
#  undef min
#endif

126
#include <OpenFlipper/BasePlugin/PluginFunctions.hh>
Jan Möbius's avatar
Jan Möbius committed
127
#include <OpenFlipper/common/ViewObjectMarker.hh>
Jan Möbius's avatar
 
Jan Möbius committed
128

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

131 132
#include <QGLFramebufferObject>

133
#include <OpenFlipper/common/RendererInfo.hh>
134 135
#include <OpenFlipper/BasePlugin/PostProcessorInterface.hh>

Jan Möbius's avatar
 
Jan Möbius committed
136 137 138 139 140 141
//== NAMESPACES ===============================================================



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

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

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


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

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

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

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

  sceneGraphRoot_   = 0;

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

Jan Möbius's avatar
 
Jan Möbius committed
190 191 192 193 194 195 196 197 198 199 200 201 202 203
  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 ();

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

208 209
  fovyModifier_ = 1.0;

210 211 212
  allowRotation_ = true;


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


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

Jan Möbius's avatar
 
Jan Möbius committed
219
  setAcceptDrops(true);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
220

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

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


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


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


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


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

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


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

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


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

Jan Möbius's avatar
Jan Möbius committed
260 261 262 263 264
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
265 266 267
{
  sceneGraphRoot_ = _root;

Jan Möbius's avatar
Jan Möbius committed
268
  if (sceneGraphRoot_ )
Jan Möbius's avatar
 
Jan Möbius committed
269 270
  {

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

  updateGL();

  emit(signalSceneGraphChanged(sceneGraphRoot_));
}


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


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


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

324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
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
344
void glViewer::perspectiveProjection()
Jan Möbius's avatar
 
Jan Möbius committed
345 346 347 348 349 350
{
  projectionMode(PERSPECTIVE_PROJECTION);
  updateGL();
}


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


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

  updateGL();
}


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

  updateProjectionMatrix();
377

378 379
  setCoordSysProjection(_p);

380
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
381 382
}

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


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

400 401 402 403 404 405 406 407 408 409 410
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
411

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

  makeCurrent();

  glstate_->reset_projection();

421
  // In stereo mode we have to use a perspective matrix
422
  if ( projectionMode_ == PERSPECTIVE_PROJECTION)
Jan Möbius's avatar
 
Jan Möbius committed
423
  {
424 425 426 427 428 429 430
    double aspect;

    if (isVisible() && glWidth() && glHeight())
      aspect = (double) glWidth() / (double) glHeight();
    else
      aspect = 1.0;

431
    // Get fovy
432
    double fovy = OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble() + fovyModifier_;
433 434

    glstate_->perspective(fovy, (GLdouble) aspect,
435
                          properties_.nearPlane(), properties_.farPlane());
Jan Möbius's avatar
Jan Möbius committed
436 437 438 439
  }
  else
  {
    double aspect;
Jan Möbius's avatar
Jan Möbius committed
440

441
    if (isVisible() && glWidth() && glHeight())
Jan Möbius's avatar
Jan Möbius committed
442 443
      aspect = (double) glWidth() / (double) glHeight();
    else
444
      aspect = 1.0;
Jan Möbius's avatar
 
Jan Möbius committed
445

446 447 448
    glstate_->ortho( -properties_.orthoWidth(), properties_.orthoWidth(),
                     -properties_.orthoWidth()/aspect, properties_.orthoWidth()/aspect,
                      properties_.nearPlane(), properties_.farPlane() );
Jan Möbius's avatar
 
Jan Möbius committed
449
  }
450

Jan Möbius's avatar
 
Jan Möbius committed
451 452 453 454 455 456
}


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


457
void glViewer::setScenePos(const ACG::Vec3d& _center, double _radius, const bool _resetTrackBall)
Jan Möbius's avatar
 
Jan Möbius committed
458
{
459
  if(_resetTrackBall) {
460
    properties_.trackballCenter(_center);
461 462
  }

463
  properties_.sceneCenter(_center);
464

465 466
  properties_.sceneRadius(_radius);
  properties_.trackballRadius(_radius);
467

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

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

   // Safety check, if near < 0
Jan Möbius's avatar
Jan Möbius committed
474
   if ( nearPlane <= 0.0 ) {
475
     std::cerr << "Error in BaseViewer drawScene, nearplane <= 0.0" << std::endl;
Jan Möbius's avatar
Jan Möbius committed
476
     nearPlane = 0.000000000000001;
477 478 479
   }

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

Jan Möbius's avatar
Jan Möbius committed
485
  properties_.setPlanes(nearPlane,farPlane);
486
  properties_.orthoWidth(_radius);
Jan Möbius's avatar
 
Jan Möbius committed
487

488 489 490 491
  updateProjectionMatrix();
  updateGL();

  emit viewChanged();
492 493 494 495 496 497
}


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


Jan Möbius's avatar
 
Jan Möbius committed
498
void glViewer::viewingDirection( const ACG::Vec3d& _dir, const ACG::Vec3d& _up )
Jan Möbius's avatar
 
Jan Möbius committed
499 500
{
  // calc eye point for this direction
501
  ACG::Vec3d eye = properties_.sceneCenter() - _dir * ( 3.0 * properties_.sceneRadius());
Jan Möbius's avatar
 
Jan Möbius committed
502 503

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

506
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
507 508
}

509 510 511 512 513 514 515
//-----------------------------------------------------------------------------

void glViewer::lookAt(const ACG::Vec3d& _eye, const ACG::Vec3d& _center, const ACG::Vec3d& _up) {
    
    glstate_->reset_modelview();
    glstate_->lookAt(_eye, _center, _up);
    
516 517
    properties_.sceneCenter( _center );
    properties_.sceneRadius( (properties_.sceneCenter() - _eye).norm() );
518 519 520
    
    emit viewChanged();
}
Jan Möbius's avatar
 
Jan Möbius committed
521 522 523

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

Jan Möbius's avatar
 
Jan Möbius committed
524
void glViewer::normalsMode(NormalsMode _mode)
Jan Möbius's avatar
 
Jan Möbius committed
525 526 527 528 529 530
{
  makeCurrent();

  switch(normalsMode_ = _mode)
  {
    case DONT_TOUCH_NORMALS:
531
      ACG::GLState::disable(GL_NORMALIZE);
Jan Möbius's avatar
 
Jan Möbius committed
532 533 534
      break;

    case NORMALIZE_NORMALS:
535
      ACG::GLState::enable(GL_NORMALIZE);
Jan Möbius's avatar
 
Jan Möbius committed
536 537 538 539 540 541 542 543 544 545 546
      break;
  }

  updateGL();
}


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


void
Jan Möbius's avatar
 
Jan Möbius committed
547
glViewer::copyToImage( QImage& _image,
Jan Möbius's avatar
Jan Möbius committed
548 549
		       unsigned int _l, unsigned int _t,
		       unsigned int _w, unsigned int _h,
550
			     GLenum /* _buffer */ )
Jan Möbius's avatar
 
Jan Möbius committed
551
{
552 553 554

//    makeCurrent();

Jan Möbius's avatar
Jan Möbius committed
555
  _image = glWidget_->grabFrameBuffer(true).copy (_l, _t, _w, _h).convertToFormat (QImage::Format_RGB32);
Jan Möbius's avatar
 
Jan Möbius committed
556 557 558 559 560 561
}


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


Jan Möbius's avatar
 
Jan Möbius committed
562
void glViewer::updateGL()
Jan Möbius's avatar
 
Jan Möbius committed
563
{
Jan Möbius's avatar
 
Jan Möbius committed
564
  if (!properties_.updateLocked() && isVisible() )
Jan Möbius's avatar
 
Jan Möbius committed
565
  {
Jan Möbius's avatar
Jan Möbius committed
566
    updatePickCache_ = true;
Jan Möbius's avatar
 
Jan Möbius committed
567
    update();
568 569

    emit viewUpdated();
Jan Möbius's avatar
 
Jan Möbius committed
570 571 572 573 574 575 576 577
  }
}



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


Jan Möbius's avatar
 
Jan Möbius committed
578
void glViewer::drawScene()
Jan Möbius's avatar
 
Jan Möbius committed
579
{
580 581 582 583
  
  // Inside the glWidget rendering, the system should not send extra updates
  properties_.blockSignals(true);
  
Jan Möbius's avatar
 
Jan Möbius committed
584 585 586
  QTime  timer;
  timer.start();

Jan Möbius's avatar
 
Jan Möbius committed
587 588 589 590
  // *****************************************************************
  // Adjust clipping planes
  // *****************************************************************
  // Far plane
591
  ACG::Vec3d c = glstate_->modelview().transform_point(properties_.sceneCenter());
Jan Möbius's avatar
 
Jan Möbius committed
592

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

  // Safety check, if near < 0
Jan Möbius's avatar
Jan Möbius committed
597
  if ( nearPlane <= 0.0 ) {
598
    std::cerr << "Error in BaseViewer drawScene, nearplane < 0" << std::endl;
Jan Möbius's avatar
Jan Möbius committed
599
    nearPlane = 0.000000000000001;
600 601 602
  }

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

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

Jan Möbius's avatar
 
Jan Möbius committed
610 611 612 613 614 615
  updateProjectionMatrix();

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

  makeCurrent();
616

Jan Möbius's avatar
Jan Möbius committed
617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642
  // 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 {
//
//  }


//  QGLFramebufferObject fbo( glstate_->viewport_width(),glstate_->viewport_height(),QGLFramebufferObject::CombinedDepthStencil );
//
//  fbo.bind();

Jan Möbius's avatar
Jan Möbius committed
643 644 645 646 647
  updatePostProcessingBufs(glstate_->viewport_width(),glstate_->viewport_height());


//  glBindFramebuffer(GL_FRAMEBUFFER, postProcessFBO_);

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
    renderManager().active( properties_.viewerId() )->plugin->render(glstate_,properties_);
Jan Möbius's avatar
Jan Möbius committed
653
  }
Jan Möbius's avatar
Jan Möbius committed
654

Jan Möbius's avatar
Jan Möbius committed
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
//  glBindFramebuffer(GL_FRAMEBUFFER, 0);






  // =================================================================================
  // Post-Processing pipeline

  readBackBuffer(glstate_);

  int numPostProcessors = postProcessorManager().numActive(properties_.viewerId());

//   // DEBUG testing post processor chain
//   if (numPostProcessors == 1)
//   {
//     postProcessorManager().append("Grayscale Postprocessor Plugin", properties_.viewerId());
//     postProcessorManager().append("Red Postprocessor Plugin", properties_.viewerId());
// 
//     numPostProcessors += 2;
//   }

  // 1st post processing source: back buffer
  int postProcSrc = 1;
  PostProcessorInput postProcInput;
  postProcInput.colorTex_ = sceneTexReadBack_.id();
  postProcInput.depthTex_ = depthTexReadBack_.id();
  postProcInput.width     = sceneTexReadBackWidth_;
  postProcInput.height    = sceneTexReadBackHeight_;


  // execute post processing chain with 2 FBOs
  for (int i = 0; i < numPostProcessors; ++i)  {

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

Jan Möbius's avatar
Jan Möbius committed
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
    GLuint targetFBO = postProcessFBO_[postProcTarget].getFboID();

    // write to back buffer in last step
    if (i + 1 == numPostProcessors)
      targetFBO = 0;

    // apply post processor
    PostProcessorInfo* proc = postProcessorManager().active( properties_.viewerId(), i );
    if (proc && proc->plugin)
      proc->plugin->postProcess(glstate_, postProcInput, targetFBO);


    // swap target/source fbo
    postProcSrc = postProcTarget;

    postProcInput.colorTex_ = postProcessFBO_[postProcSrc].getAttachment(GL_COLOR_ATTACHMENT0);
708
  }
Jan Möbius's avatar
Jan Möbius committed
709 710 711 712 713 714

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

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

715 716 717
  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, 0);

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

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

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

Jan Möbius's avatar
 
Jan Möbius committed
736 737 738 739 740 741
}


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


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

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

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

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

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

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

Jan Möbius's avatar
Jan Möbius committed
780 781 782
    // 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
783

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

794
      glPushAttrib(GL_ALL_ATTRIB_BITS);
795

796
      ACG::GLState::enable(GL_BLEND);
797 798 799
      ACG::GLState::disable(GL_DEPTH_TEST);
      ACG::GLState::disable(GL_LIGHTING);
      ACG::GLState::disable(GL_DITHER);
800

801 802
      int vp_l, vp_b, vp_w, vp_h;
      glstate_->get_viewport (vp_l, vp_b, vp_w, vp_h);
803

804 805 806 807 808 809 810
      glMatrixMode(GL_PROJECTION);
      glPushMatrix ();
      glLoadIdentity();
      glOrtho(0, vp_w, vp_h, 0, 0, 1.0);
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix ();
      glLoadIdentity();
811

812
      glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
813

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

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

830 831
        if (!ok)
          continue;
832

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

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

838 839 840 841 842 843 844 845
        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
846

847 848 849 850
      glMatrixMode(GL_PROJECTION);
      glPopMatrix ();
      glMatrixMode(GL_MODELVIEW);
      glPopMatrix ();
Jan Möbius's avatar
 
Jan Möbius committed
851

852
      glPopAttrib ();
853
      ACG::GLState::disable (GL_STENCIL_TEST);
Jan Möbius's avatar
 
Jan Möbius committed
854
    }
855 856


Jan Möbius's avatar
 
Jan Möbius committed
857
  }
Jan Möbius's avatar
Jan Möbius committed
858

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

Jan Möbius's avatar
 
Jan Möbius committed
871 872
}

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


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

893
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
894 895 896 897 898

}

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

Jan Möbius's avatar
 
Jan Möbius committed
899
void glViewer::viewAll()
Jan Möbius's avatar
 
Jan Möbius committed
900
{
901
  makeCurrent();
Jan Möbius's avatar
 
Jan Möbius committed
902

903 904
  // 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
905

906 907 908
  // 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()));
909

910 911 912 913
  properties_.orthoWidth( 1.1 * properties_.sceneRadius() );
  double aspect = (double) glWidth() / (double) glHeight();
  if (aspect > 1.0)
    properties_.orthoWidth( aspect * properties_.orthoWidth() ) ;
914

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

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

921 922 923
  properties_.unLockUpdate();
  updateProjectionMatrix();
  updateGL();
924

925
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
926 927 928 929 930 931 932

}


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


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

940
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
941 942 943 944 945 946
}


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


Jan Möbius's avatar
 
Jan Möbius committed
947
void glViewer::initializeGL()
Jan Möbius's avatar
 
Jan Möbius committed
948 949 950
{

  // lock update
951
  properties_.lockUpdate();
Jan Möbius's avatar
 
Jan Möbius committed
952 953 954 955 956

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

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


  projectionMode(   projectionMode_   );
  normalsMode(      normalsMode_      );

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

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

988 989 990 991
  initialized_ = true;

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

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

    viewAll();
999
  }
Jan Möbius's avatar
 
Jan Möbius committed
1000 1001 1002 1003 1004 1005
}


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


Jan Möbius's avatar
 
Jan Möbius committed
1006
void glViewer::paintGL()
Jan Möbius's avatar
 
Jan Möbius committed
1007
{
1008 1009
  if (!initialized_)
    initializeGL ();
Jan Möbius's avatar
 
Jan Möbius committed
1010

1011
  if (!properties_.updateLocked())
Jan Möbius's avatar
 
Jan Möbius committed
1012
  {
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
1013 1014
    ACG::Vec4f clear_color;

1015
    properties_.lockUpdate();
Jan Möbius's avatar
 
Jan Möbius committed
1016 1017 1018

    glPushAttrib (GL_ALL_ATTRIB_BITS);

1019 1020
    ACG::GLState::enable(GL_DEPTH_TEST);
    ACG::GLState::enable(GL_LIGHTING);
1021
    ACG::GLState::disable(GL_DITHER);
1022
    ACG::GLState::shadeModel( GL_FLAT );
Jan Möbius's avatar
 
Jan Möbius committed
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();


    normalsMode(      normalsMode_      );

1033
    applyProperties();
1034

1035
    glstate_->setState();
Jan Möbius's avatar
 
Jan Möbius committed
1036 1037 1038

    glColor4f(1.0,0.0,0.0,1.0);

1039
    glstate_->clearBuffers ();
Jan Möbius's avatar
 
Jan Möbius committed
1040

1041
    properties_.unLockUpdate();
Jan Möbius's avatar
 
Jan Möbius committed
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052

    // draw scene
    drawScene();

    glPopMatrix();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    glPopAttrib ();
  }
1053

Jan Möbius's avatar
 
Jan Möbius committed
1054 1055 1056 1057 1058 1059
}


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


Jan Möbius's avatar
 
Jan Möbius committed
1060
void glViewer::resizeEvent(QGraphicsSceneResizeEvent *)
Jan Möbius's avatar
 
Jan Möbius committed
1061 1062
{
  updateProjectionMatrix();
Jan Möbius's avatar
 
Jan Möbius committed
1063
  glstate_->viewport(scenePos().x(),