QtBaseViewer.cc 61.6 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 67 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 <ACG/GL/gl.hh>

#include <iostream>
#include <string>
#include <assert.h>

#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>
105
#include <QGLFramebufferObjectFormat>
Jan Möbius's avatar
 
Jan Möbius committed
106 107
#include <QPainter>
#include <QPaintEngine>
Jan Möbius's avatar
 
Jan Möbius committed
108

109 110
#include <QImageWriter>

Jan Möbius's avatar
 
Jan Möbius committed
111 112 113 114 115 116 117 118
#ifdef max
#  undef max
#endif

#ifdef min
#  undef min
#endif

119
#include <OpenFlipper/BasePlugin/PluginFunctions.hh>
Jan Möbius's avatar
Jan Möbius committed
120
#include <OpenFlipper/common/ViewObjectMarker.hh>
Jan Möbius's avatar
 
Jan Möbius committed
121

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

124 125
#include <QGLFramebufferObject>

126
#include <OpenFlipper/common/RendererInfo.hh>
127 128
#include <OpenFlipper/BasePlugin/PostProcessorInterface.hh>

Jan Möbius's avatar
 
Jan Möbius committed
129 130 131 132 133 134
//== NAMESPACES ===============================================================



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

135
static const char          COPY_PASTE_VIEW_START_STRING[] =
Jan Möbius's avatar
 
Jan Möbius committed
136 137 138 139 140
  "ACG::QtWidgets::QGLViewerWidget encoded view";

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


141
glViewer::glViewer( QGraphicsScene* _scene,
142
                    QGLWidget* _glWidget,
143
                    Viewer::ViewerProperties& _properties,
144
                    QGraphicsWidget* _parent) :
Jan Möbius's avatar
 
Jan Möbius committed
145
  QGraphicsWidget(_parent),
Jan Möbius's avatar
 
Jan Möbius committed
146 147
  glareaGrabbed_(false),
  projectionUpdateLocked_(false),
Jan Möbius's avatar
 
Jan Möbius committed
148 149
  glScene_(_scene),
  glWidget_(_glWidget),
Jan Möbius's avatar
Jan Möbius committed
150 151 152
  pickCache_(0),
  updatePickCache_(true),
  pickCacheSupported_(true),
153
  clickEvent_(QEvent::MouseButtonPress, QPoint (), Qt::NoButton, Qt::NoButton, Qt::NoModifier),
Dirk Wilden's avatar
Dirk Wilden committed
154
  properties_(_properties),
155
  glstate_(0),
Jan Möbius's avatar
Jan Möbius committed
156 157 158 159 160 161
  initialized_(false),
  flyAnimationPerspective_(0),
  flyAnimationOrthogonal_(0),
  flyAngle_(0.0),
  currentAnimationPos_(0.0),
  flyMoveBack_(false)
Jan Möbius's avatar
 
Jan Möbius committed
162 163 164
{

  // widget stuff
165
  createWidgets();
Jan Möbius's avatar
 
Jan Möbius committed
166 167 168

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

Jan Möbius's avatar
 
Jan Möbius committed
171 172
  // state
  isRotating_       = false;
Mike Kremer's avatar
Mike Kremer committed
173
  lookAround_       = false;
Jan Möbius's avatar
 
Jan Möbius committed
174 175 176

  sceneGraphRoot_   = 0;

177
  normalsMode_      = NORMALIZE_NORMALS;
Jan Möbius's avatar
 
Jan Möbius committed
178
  projectionMode_   = PERSPECTIVE_PROJECTION;
Jan Möbius's avatar
Jan Möbius committed
179
  navigationMode_   = NORMAL_NAVIGATION;
180

Jan Möbius's avatar
 
Jan Möbius committed
181 182 183 184 185 186 187 188 189 190 191 192 193 194
  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 ();

195 196 197 198 199 200 201
  // timer for animation
  timer_ = new QTimer( this );
  connect( timer_, SIGNAL(timeout()), this, SLOT( slotAnimation()) );

  allowRotation_ = true;


Jan Möbius's avatar
 
Jan Möbius committed
202 203 204
  connect( &properties_,SIGNAL(updated()), this, SLOT( slotPropertiesUpdated() ) );


Dirk Wilden's avatar
Dirk Wilden committed
205 206 207
  //check for updated properties once
  slotPropertiesUpdated();

Jan Möbius's avatar
 
Jan Möbius committed
208
  setAcceptDrops(true);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
209

210
  setHome();
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
211

212 213
  clickTimer_.setSingleShot (true);
  connect (&clickTimer_, SIGNAL(timeout ()), this, SLOT(slotClickTimeout ()));
Jan Möbius's avatar
 
Jan Möbius committed
214 215 216 217 218 219
}


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


Jan Möbius's avatar
 
Jan Möbius committed
220
glViewer::~glViewer()
Jan Möbius's avatar
 
Jan Möbius committed
221 222 223 224 225 226 227 228
{
  delete glstate_;
}


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


229 230 231 232 233
//QSizeF
//glViewer::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const
//{
//  return QSizeF( 600, 600 );
//}
Jan Möbius's avatar
 
Jan Möbius committed
234 235 236 237

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


Jan Möbius's avatar
 
Jan Möbius committed
238
void glViewer::makeCurrent() {
Jan Möbius's avatar
 
Jan Möbius committed
239 240 241
  glWidget_->makeCurrent();
}

Jan Möbius's avatar
 
Jan Möbius committed
242
void glViewer::swapBuffers() {
Jan Möbius's avatar
 
Jan Möbius committed
243 244 245 246 247 248
  glWidget_->swapBuffers();
}


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

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

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

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

  updateGL();

  emit(signalSceneGraphChanged(sceneGraphRoot_));
}


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


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


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

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


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


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

  updateGL();
}


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

  updateProjectionMatrix();
366

367 368
  setCoordSysProjection(_p);

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

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


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

389 390 391 392 393 394 395 396 397 398 399
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
400

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

  makeCurrent();

  glstate_->reset_projection();

410
  // In stereo mode we have to use a perspective matrix
411
  if ( projectionMode_ == PERSPECTIVE_PROJECTION)
Jan Möbius's avatar
 
Jan Möbius committed
412
  {
413 414 415 416 417 418 419
    double aspect;

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

420 421 422 423
    // Get fovy
    double fovy = OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble();

    glstate_->perspective(fovy, (GLdouble) aspect,
424
                          properties_.nearPlane(), properties_.farPlane());
Jan Möbius's avatar
Jan Möbius committed
425 426 427 428
  }
  else
  {
    double aspect;
Jan Möbius's avatar
Jan Möbius committed
429

430
    if (isVisible() && glWidth() && glHeight())
Jan Möbius's avatar
Jan Möbius committed
431 432
      aspect = (double) glWidth() / (double) glHeight();
    else
433
      aspect = 1.0;
Jan Möbius's avatar
 
Jan Möbius committed
434

435 436 437
    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
438
  }
439

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


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


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

452
  properties_.sceneCenter(_center);
453

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

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

  // Set far plane
460
  properties_.farPlane( std::max(0.0002f * properties_.sceneRadius(),  -(c[2] - properties_.sceneRadius() )) );
Jan Möbius's avatar
 
Jan Möbius committed
461

462
  // Set near plane
463
  properties_.nearPlane( std::max(0.0001f * properties_.sceneRadius(),  -(c[2] + properties_.sceneRadius())) );
464
  
465 466 467 468
  updateProjectionMatrix();
  updateGL();

  emit viewChanged();
469 470 471 472 473 474
}


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


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

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

483
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
484 485
}

486 487 488 489 490 491 492
//-----------------------------------------------------------------------------

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

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

Jan Möbius's avatar
 
Jan Möbius committed
501
void glViewer::normalsMode(NormalsMode _mode)
Jan Möbius's avatar
 
Jan Möbius committed
502 503 504 505 506 507
{
  makeCurrent();

  switch(normalsMode_ = _mode)
  {
    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 514 515 516 517 518 519 520 521 522 523
      break;
  }

  updateGL();
}


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


void
Jan Möbius's avatar
 
Jan Möbius committed
524
glViewer::copyToImage( QImage& _image,
Jan Möbius's avatar
Jan Möbius committed
525 526
		       unsigned int _l, unsigned int _t,
		       unsigned int _w, unsigned int _h,
527
			     GLenum /* _buffer */ )
Jan Möbius's avatar
 
Jan Möbius committed
528
{
529 530 531

//    makeCurrent();

Jan Möbius's avatar
Jan Möbius committed
532
  _image = glWidget_->grabFrameBuffer(true).copy (_l, _t, _w, _h).convertToFormat (QImage::Format_RGB32);
Jan Möbius's avatar
 
Jan Möbius committed
533 534 535 536 537 538
}


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


Jan Möbius's avatar
 
Jan Möbius committed
539
void glViewer::updateGL()
Jan Möbius's avatar
 
Jan Möbius committed
540
{
Jan Möbius's avatar
 
Jan Möbius committed
541
  if (!properties_.updateLocked() && isVisible() )
Jan Möbius's avatar
 
Jan Möbius committed
542
  {
Jan Möbius's avatar
Jan Möbius committed
543
    updatePickCache_ = true;
Jan Möbius's avatar
 
Jan Möbius committed
544
    update();
545 546

    emit viewUpdated();
Jan Möbius's avatar
 
Jan Möbius committed
547 548 549 550 551 552 553 554
  }
}



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


Jan Möbius's avatar
 
Jan Möbius committed
555
void glViewer::drawScene()
Jan Möbius's avatar
 
Jan Möbius committed
556
{
557 558 559 560
  
  // Inside the glWidget rendering, the system should not send extra updates
  properties_.blockSignals(true);
  
Jan Möbius's avatar
 
Jan Möbius committed
561 562 563
  QTime  timer;
  timer.start();

Jan Möbius's avatar
 
Jan Möbius committed
564 565 566 567
  // *****************************************************************
  // Adjust clipping planes
  // *****************************************************************
  // Far plane
568
  ACG::Vec3d c = glstate_->modelview().transform_point(properties_.sceneCenter());
Jan Möbius's avatar
 
Jan Möbius committed
569 570

  // Set far plane
571
  properties_.farPlane( std::max(0.0002f * properties_.sceneRadius(),  -(c[2] - properties_.sceneRadius())) );
Jan Möbius's avatar
 
Jan Möbius committed
572 573

  // Set near plane
574
  properties_.nearPlane( std::max(0.0001f * properties_.sceneRadius(),  -(c[2] + properties_.sceneRadius())) );
Jan Möbius's avatar
 
Jan Möbius committed
575

Jan Möbius's avatar
 
Jan Möbius committed
576 577 578 579 580 581 582
  updateProjectionMatrix();

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

  // draw mono or stereo
  makeCurrent();
583

584
  // Check if we use build in default renderer
Jan Möbius's avatar
Jan Möbius committed
585
  if ( renderManager().activeId( properties_.viewerId() ) == 0 ) {
586
    drawScene_mono();
Jan Möbius's avatar
Jan Möbius committed
587
  } else {
588
    renderManager().active( properties_.viewerId() )->plugin->render(glstate_,properties_);
Jan Möbius's avatar
Jan Möbius committed
589
  }
590
  
Jan Möbius's avatar
Jan Möbius committed
591 592
  if ( postProcessorManager().activeId( properties_.viewerId() ) != 0 ) {
    postProcessorManager().active( properties_.viewerId() )->plugin->postProcess(glstate_);
593
  }
594
  
Jan Möbius's avatar
 
Jan Möbius committed
595
  glFinish();
Jan Möbius's avatar
Jan Möbius committed
596

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

599 600 601
  
  // Inside the glWidget rendering, the system should not send extra updates
  properties_.blockSignals(false);
Jan Möbius's avatar
Jan Möbius committed
602

Jan Möbius's avatar
 
Jan Möbius committed
603 604 605 606 607 608
}


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


Jan Möbius's avatar
 
Jan Möbius committed
609
void glViewer::drawScene_mono()
Jan Möbius's avatar
 
Jan Möbius committed
610
{
611 612 613 614
  if (sceneGraphRoot_) {
    ViewObjectMarker *oM = properties_.objectMarker();
    GLuint refBits = 0;
    QSet<GLuint> references;
615

616 617 618
    if (oM)
    {
      glClear (GL_STENCIL_BUFFER_BIT);
619
      ACG::GLState::enable (GL_STENCIL_TEST);
620 621
      glStencilOp (GL_KEEP, GL_KEEP, GL_ZERO);
      glStencilFunc (GL_ALWAYS, 0, ~0);
622

623 624
      for (PluginFunctions::ObjectIterator o_it(PluginFunctions::ALL_OBJECTS, DATA_ALL) ;
          o_it != PluginFunctions::objectsEnd(); ++o_it)
625
      {
626 627 628 629
        bool ok;
        GLuint ref;

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

631
        if (ok)
632
        {
633 634 635 636
          o_it->stencilRefNode ()->setReference (ref);
          o_it->stencilRefNode ()->show ();
          refBits |= ref;
          references << ref;
637
        }
638 639
        else
          o_it->stencilRefNode ()->hide ();
640
      }
641 642
    }

Jan Möbius's avatar
Jan Möbius committed
643 644 645
    // First pass
    ACG::SceneGraph::DrawAction pass1( properties_.drawMode(), *glstate_ , false);
    ACG::SceneGraph::traverse_multipass(sceneGraphRoot_, pass1, *glstate_, properties_.drawMode() );
646

Jan Möbius's avatar
Jan Möbius committed
647 648 649
    // 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
650

651 652 653
    if (oM)
    {
      if (oM->type() == ViewObjectMarker::PerBit)
Jan Möbius's avatar
 
Jan Möbius committed
654
      {
655 656 657 658
        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
659
      }
660

661
      glPushAttrib(GL_ALL_ATTRIB_BITS);
662

663
      ACG::GLState::enable(GL_BLEND);
664 665 666
      ACG::GLState::disable(GL_DEPTH_TEST);
      ACG::GLState::disable(GL_LIGHTING);
      ACG::GLState::disable(GL_DITHER);
667

668 669
      int vp_l, vp_b, vp_w, vp_h;
      glstate_->get_viewport (vp_l, vp_b, vp_w, vp_h);
670

671 672 673 674 675 676 677
      glMatrixMode(GL_PROJECTION);
      glPushMatrix ();
      glLoadIdentity();
      glOrtho(0, vp_w, vp_h, 0, 0, 1.0);
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix ();
      glLoadIdentity();
678

679
      glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
680

681 682 683 684 685 686 687
      foreach (unsigned int ref, references)
      {
        bool ok;
        GLenum sfactor;
        GLenum dfactor;
        ACG::Vec4f color;
        unsigned int mask = ~0;
688

689
        if (oM->type() == ViewObjectMarker::PerBit)
690
        {
691 692
          ok = oM->blendForStencilRefBit (ref, sfactor, dfactor, color);
          mask = ref;
693
        }
694 695
        else
          ok = oM->blendForStencilRefNumber (ref, sfactor, dfactor, color);
696

697 698
        if (!ok)
          continue;
699

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

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

705 706 707 708 709 710 711 712
        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
713

714 715 716 717
      glMatrixMode(GL_PROJECTION);
      glPopMatrix ();
      glMatrixMode(GL_MODELVIEW);
      glPopMatrix ();
Jan Möbius's avatar
 
Jan Möbius committed
718

719
      glPopAttrib ();
720
      ACG::GLState::disable (GL_STENCIL_TEST);
Jan Möbius's avatar
 
Jan Möbius committed
721
    }
722 723


Jan Möbius's avatar
 
Jan Möbius committed
724
  }
Jan Möbius's avatar
Jan Möbius committed
725

726
  if (properties_.cursorPainter() && properties_.cursorPainter()->enabled () && properties_.cursorPositionValid() )
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
727 728 729 730 731
  {
    glstate_->push_modelview_matrix ();
    // reset view transformation
    glstate_->reset_modelview ();
    // translate cursor position to 0,0
732
    glstate_->translate ( properties_.cursorPoint3D() );
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
733
    // paint cursor
734
    properties_.cursorPainter()->paintCursor (glstate_);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
735 736
    glstate_->pop_modelview_matrix ();
  }
737

Jan Möbius's avatar
 
Jan Möbius committed
738 739
}

Jan Möbius's avatar
 
Jan Möbius committed
740
void glViewer::setHome()
Jan Möbius's avatar
 
Jan Möbius committed
741 742 743
{
  home_modelview_          = glstate_->modelview();
  home_inverse_modelview_  = glstate_->inverse_modelview();
744
  homeOrthoWidth_          = properties_.orthoWidth();
745 746
  home_center_             = properties_.trackballCenter();
  home_radius_             = properties_.trackballRadius();
Jan Möbius's avatar
 
Jan Möbius committed
747 748 749
}


Jan Möbius's avatar
 
Jan Möbius committed
750
void glViewer::home()
Jan Möbius's avatar
 
Jan Möbius committed
751 752 753
{
  makeCurrent();
  glstate_->set_modelview(home_modelview_, home_inverse_modelview_);
754
  properties_.orthoWidth( homeOrthoWidth_ );
755 756
  properties_.trackballCenter( home_center_ );
  properties_.trackballRadius(home_radius_);
Jan Möbius's avatar
 
Jan Möbius committed
757 758
  updateProjectionMatrix();
  updateGL();
759

760
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
761 762 763 764 765

}

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

Jan Möbius's avatar
 
Jan Möbius committed
766
void glViewer::viewAll()
Jan Möbius's avatar
 
Jan Möbius committed
767
{
768
  makeCurrent();
Jan Möbius's avatar
 
Jan Möbius committed
769

770 771
  // 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
772

773 774 775
  // 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()));
776

777 778 779 780
  properties_.orthoWidth( 1.1 * properties_.sceneRadius() );
  double aspect = (double) glWidth() / (double) glHeight();
  if (aspect > 1.0)
    properties_.orthoWidth( aspect * properties_.orthoWidth() ) ;
781

Jan Möbius's avatar
Jan Möbius committed
782 783 784 785 786
  unsigned int maxPases = 1;
  ACG::Vec3d bbmin,bbmax;
  ACG::SceneGraph::analyzeSceneGraph(PluginFunctions::getSceneGraphRootNode(),maxPases,bbmin,bbmax);

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

788 789 790
  properties_.unLockUpdate();
  updateProjectionMatrix();
  updateGL();
791

792
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
793 794 795 796 797 798 799

}


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


Jan Möbius's avatar
 
Jan Möbius committed
800
void glViewer::setView(const ACG::GLMatrixd& _modelview,
Jan Möbius's avatar
 
Jan Möbius committed
801 802 803 804 805
			                  const ACG::GLMatrixd& _inverse_modelview)
{
  makeCurrent();
  glstate_->set_modelview(_modelview, _inverse_modelview);
  updateGL();
806

807
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
808 809 810 811 812 813
}


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


Jan Möbius's avatar
 
Jan Möbius committed
814
void glViewer::initializeGL()
Jan Möbius's avatar
 
Jan Möbius committed
815 816 817
{

  // lock update
818
  properties_.lockUpdate();
Jan Möbius's avatar
 
Jan Möbius committed
819 820 821 822 823

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

  // OpenGL state
824 825
  ACG::GLState::enable(GL_DEPTH_TEST);
  ACG::GLState::enable(GL_LIGHTING);
826
  ACG::GLState::disable(GL_DITHER);
827
  ACG::GLState::shadeModel( GL_FLAT );
Jan Möbius's avatar
 
Jan Möbius committed
828 829 830 831 832


  projectionMode(   projectionMode_   );
  normalsMode(      normalsMode_      );

833
  // Update all settings which would require a redraw
834
  applyProperties();
Jan Möbius's avatar
 
Jan Möbius committed
835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852

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

855 856 857 858
  initialized_ = true;

  if (sceneGraphRoot_)
  {
Jan Möbius's avatar
Jan Möbius committed
859 860 861 862 863 864 865
    unsigned int maxPases = 1;
    ACG::Vec3d bbmin,bbmax;
    ACG::SceneGraph::analyzeSceneGraph(sceneGraphRoot_,maxPases,bbmin,bbmax);

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

    viewAll();
866
  }
Jan Möbius's avatar
 
Jan Möbius committed
867 868 869 870 871 872
}


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


Jan Möbius's avatar
 
Jan Möbius committed
873
void glViewer::paintGL()
Jan Möbius's avatar
 
Jan Möbius committed
874
{
875 876
  if (!initialized_)
    initializeGL ();
Jan Möbius's avatar
 
Jan Möbius committed
877

878
  if (!properties_.updateLocked())
Jan Möbius's avatar
 
Jan Möbius committed
879
  {
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
880 881
    ACG::Vec4f clear_color;

882
    properties_.lockUpdate();
Jan Möbius's avatar
 
Jan Möbius committed
883 884 885

    glPushAttrib (GL_ALL_ATTRIB_BITS);

886 887
    ACG::GLState::enable(GL_DEPTH_TEST);
    ACG::GLState::enable(GL_LIGHTING);
888
    ACG::GLState::disable(GL_DITHER);
889
    ACG::GLState::shadeModel( GL_FLAT );
Jan Möbius's avatar
 
Jan Möbius committed
890 891 892 893 894 895 896 897 898 899

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();


    normalsMode(      normalsMode_      );

900
    applyProperties();
901

902
    glstate_->setState();
Jan Möbius's avatar
 
Jan Möbius committed
903 904 905

    glColor4f(1.0,0.0,0.0,1.0);

906
    glstate_->clearBuffers ();
Jan Möbius's avatar
 
Jan Möbius committed
907

908
    properties_.unLockUpdate();
Jan Möbius's avatar
 
Jan Möbius committed
909 910 911 912 913 914 915 916 917 918 919

    // draw scene
    drawScene();

    glPopMatrix();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    glPopAttrib ();
  }
920

Jan Möbius's avatar
 
Jan Möbius committed
921 922 923 924 925 926
}


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


Jan Möbius's avatar
 
Jan Möbius committed
927
void glViewer::resizeEvent(QGraphicsSceneResizeEvent *)
Jan Möbius's avatar
 
Jan Möbius committed
928 929
{
  updateProjectionMatrix();
Jan Möbius's avatar
 
Jan Möbius committed
930
  glstate_->viewport(scenePos().x(),
Jan Möbius's avatar
Jan Möbius committed
931 932 933
                     scene()->height () - scenePos().y() - size().height (),
                     size().width (), size().height (),
                     scene()->width (), scene()->height ());
Jan Möbius's avatar
 
Jan Möbius committed
934
  update();
935

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

Jan Möbius's avatar
 
Jan Möbius committed
939 940 941
void glViewer::moveEvent (QGraphicsSceneMoveEvent *)
{
  glstate_->viewport(scenePos().x(),
Jan Möbius's avatar
Jan Möbius committed
942 943 944
                     scene()->height () - scenePos().y() - size().height (),
                     size().width (), size().height (),
                     scene()->width (), scene()->height ());
Jan Möbius's avatar
 
Jan Möbius committed
945
  update();
946

947
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
948
}
Jan Möbius's avatar
 
Jan Möbius committed
949 950 951

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

952
void glViewer::encodeView(QString& _view, const QSize& _windowSize /*= QSize()*/, const int _splitterWidth /*=-1*/)
Jan Möbius's avatar
 
Jan Möbius committed
953
{
954
  // Get current matrices
Jan Möbius's avatar
 
Jan Möbius committed
955 956 957
  const ACG::GLMatrixd m = glstate_->modelview();
  const ACG::GLMatrixd p = glstate_->projection();

958
  // Add modelview matrix to output
959
  _view += QString(COPY_PASTE_VIEW_START_STRING) + "\n";
960 961 962 963 964 965 966 967 968 969 970 971
  _view += QString::number(m(0,0)) + " " + QString::number(m(0,1)) + " " + QString::number(m(0,2)) + " " + QString::number(m(0,3)) + "\n";
  _view += QString::number(m(1,0)) + " " + QString::number(m(1,1)) + " " + QString::number(m(1,2)) + " " + QString::number(m(1,3)) + "\n";
  _view += QString::number(m(2,0)) + " " + QString::number(m(2,1)) + " " + QString::number(m(2,2)) + " " + QString::number(m(2,3)) + "\n";
  _view += QString::number(m(3,0)) + " " + QString::number(m(3,1)) + " " + QString::number(m(3,2)) + " " + QString::number(m(3,3)) + "\n";

  // Add projection matrix to output
  _view += QString::number(p(0,0)) + " " + QString::number(p(0,1)) + " " + QString::number(p(0,2)) + " " + QString::number(p(0,3)) + "\n";
  _view += QString::number(p(1,0)) + " " + QString::number(p(1,1)) + " " + QString::number(p(1,2)) + " " + QString::number(p(1,3)) + "\n";
  _view += QString::number(p(2,0)) + " " + QString::number(p(2,1)) + " " + QString::number(p(2,2)) + " " + QString::number(p(2,3)) + "\n";
  _view += QString::number(p(3,0)) + " " + QString::number(p(3,1)) + " " + QString::number(p(3,2)) + " " + QString::number(p(3,3)) + "\n";

  // add gl width/height, current projection Mode and the ortho mode width to output
972
  _view += QString::number(_windowSize.width()) + " " +  QString::number(_windowSize.height()) + " "  + QString::number(_splitterWidth)+ " " + QString::number(projectionMode_) + " " + QString::number(properties_.orthoWidth()) + "\n";
Jan Möbius's avatar
 
Jan Möbius committed
973 974 975 976 977 978
}


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


979
bool glViewer::decodeView(const QString& _view, QSize *_windowSize /*= NULL*/, int* _splitterWidth /*= NULL*/)
Jan Möbius's avatar
 
Jan Möbius committed
980
{
981 982 983
  if (_view.left(sizeof(COPY_PASTE_VIEW_START_STRING)-1) != QString(COPY_PASTE_VIEW_START_STRING))
  {
    std::cerr << "No View was copied." << std::endl;
Jan Möbius's avatar
 
Jan Möbius committed
984
    return false;
985
  }
Jan Möbius's avatar
 
Jan Möbius committed
986

987 988
  // Remove the magic from the string
  QString temp = _view;
989
  temp.remove(0,sizeof(COPY_PASTE_VIEW_START_STRING));
Jan Möbius's avatar
 
Jan Möbius committed
990

991 992
  //Split it into its components
  QStringList split = temp.split(QRegExp("[\\n\\s]"),QString::SkipEmptyParts);
Jan Möbius's avatar
 
Jan Möbius committed
993 994

  ACG::GLMatrixd m, p;
Jan Möbius's avatar
Jan Möbius committed
995
  int            pMode;
Jan Möbius's avatar
 
Jan Möbius committed
996

997 998 999 1000 1001 1002 1003 1004
  // New version
  if ( split.size() == 37 ) {

    //*********************************************************
    // Parse the components
    // first, get the projection and the modelview matrices
    //*********************************************************
    for (std::size_t i = 0; i < 4; ++i)
1005
    {
1006