QtBaseViewer.cc 61.2 KB
Newer Older
Jan Möbius's avatar
Jan Möbius committed
1 2 3
/*===========================================================================*\
*                                                                            *
*                              OpenFlipper                                   *
Jan Möbius's avatar
Jan Möbius committed
4
*      Copyright (C) 2001-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 59
#include <ACG/QtWidgets/QtWheel.hh>
#include <ACG/Scenegraph/DrawModes.hh>
60
#include <ACG/Scenegraph/CoordsysNode.hh>
Jan Möbius's avatar
 
Jan Möbius committed
61 62 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
#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>

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

107 108
#include <QImageWriter>

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

#ifdef min
#  undef min
#endif

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

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

122 123
#include <QGLFramebufferObject>

124
#include <OpenFlipper/common/RendererInfo.hh>
125 126
#include <OpenFlipper/BasePlugin/PostProcessorInterface.hh>

Jan Möbius's avatar
 
Jan Möbius committed
127 128 129 130 131 132
//== NAMESPACES ===============================================================



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

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

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


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

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

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

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

  sceneGraphRoot_   = 0;

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

Jan Möbius's avatar
 
Jan Möbius committed
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
  trackMouse_ = false;

  // stereo
  stereo_ = 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 ();

199 200 201 202 203 204 205
  // 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
206 207 208
  connect( &properties_,SIGNAL(updated()), this, SLOT( slotPropertiesUpdated() ) );


Dirk Wilden's avatar
Dirk Wilden committed
209 210 211
  //check for updated properties once
  slotPropertiesUpdated();

Jan Möbius's avatar
 
Jan Möbius committed
212
  setAcceptDrops(true);
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
213

214
  setHome();
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
215 216 217 218 219 220 221 222

  // initialize custom anaglyph stereo
  agTexWidth_ = 0;
  agTexHeight_ = 0;
  agTexture_[0] = 0;
  agTexture_[1] = 0;
  agProgram_ = 0;
  customAnaglyphSupported_ = false;
223 224 225

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


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


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


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


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

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


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

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


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


263
void glViewer::sceneGraph(ACG::SceneGraph::BaseNode* _root, const bool _resetTrackBall)
Jan Möbius's avatar
 
Jan Möbius committed
264 265 266
{
  sceneGraphRoot_ = _root;

Jan Möbius's avatar
Jan Möbius committed
267
  if (sceneGraphRoot_ )
Jan Möbius's avatar
 
Jan Möbius committed
268
  {
Jan Möbius's avatar
Jan Möbius committed
269 270 271 272 273 274 275 276
    
    // set max number of render pass
    // Single pass action, this info is static during multipass
    ACG::SceneGraph::MultiPassInfoAction info_act;
    ACG::SceneGraph::traverse(sceneGraphRoot_, info_act);
    
    glstate_->set_max_render_passes(info_act.getMaxPasses());
    
Jan Möbius's avatar
 
Jan Möbius committed
277
    // get scene size
Jan Möbius's avatar
Jan Möbius committed
278
    // Single pass action, as the bounding box is not influenced by multipass traversal
Jan Möbius's avatar
 
Jan Möbius committed
279 280 281 282 283
    ACG::SceneGraph::BoundingBoxAction act;
    ACG::SceneGraph::traverse(sceneGraphRoot_, act);

    ACG::Vec3d bbmin = (ACG::Vec3d) act.bbMin();
    ACG::Vec3d bbmax = (ACG::Vec3d) act.bbMax();
Jan Möbius's avatar
Jan Möbius committed
284 285
    
    
Jan Möbius's avatar
 
Jan Möbius committed
286 287 288

    if ( ( bbmin[0] > bbmax[0] ) ||
         ( bbmin[1] > bbmax[1] ) ||
289 290 291
         ( bbmin[2] > bbmax[2] )   ) {
      
      // Invalid bounding box, try to recover
292
      setScenePos( ACG::Vec3d( 0.0,0.0,0.0 ) , 1.0, _resetTrackBall );
293 294 295 296
    
      // Update bounding box to match the scene geometry after recovery
      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
297 298
    } else {
      
299
      // For very small scenes, we set the scene radius to 0.1
Jan Möbius's avatar
Jan Möbius committed
300
      // otherwise we take the real radius
301
      if ( ( bbmax - bbmin ).max() < OpenFlipperSettings().value("Core/Gui/glViewer/minimalSceneSize",0.1).toDouble() )  {
Jan Möbius's avatar
Jan Möbius committed
302
        setScenePos( ( bbmin + bbmax )        * 0.5,
303
                     OpenFlipperSettings().value("Core/Gui/glViewer/minimalSceneSize",0.1).toDouble(),
Jan Möbius's avatar
Jan Möbius committed
304 305 306 307 308 309 310 311 312
                     _resetTrackBall);
                   
      } else {
        setScenePos( ( bbmin + bbmax )        * 0.5,
                     ( bbmax - bbmin ).norm() * 0.5,
                     _resetTrackBall); 
      }
                   
    }
313 314 315 316
                   
    // remember the new bounding box for the state
    glstate_->set_bounding_box(bbmin,bbmax);
    
Jan Möbius's avatar
 
Jan Möbius committed
317
  }
318
  
Jan Möbius's avatar
 
Jan Möbius committed
319 320 321 322 323 324 325 326 327 328

  updateGL();

  emit(signalSceneGraphChanged(sceneGraphRoot_));
}


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


Jan Möbius's avatar
 
Jan Möbius committed
329
void glViewer::trackMouse(bool _track)
Jan Möbius's avatar
 
Jan Möbius committed
330 331 332 333 334 335 336
{
  trackMouse_ = _track;
}


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

337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
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
357
void glViewer::perspectiveProjection()
Jan Möbius's avatar
 
Jan Möbius committed
358 359 360 361 362 363
{
  projectionMode(PERSPECTIVE_PROJECTION);
  updateGL();
}


Jan Möbius's avatar
 
Jan Möbius committed
364
void glViewer::orthographicProjection()
Jan Möbius's avatar
 
Jan Möbius committed
365 366 367 368 369 370
{
  projectionMode(ORTHOGRAPHIC_PROJECTION);
  updateGL();
}


Jan Möbius's avatar
 
Jan Möbius committed
371
void glViewer::toggleProjectionMode()
Jan Möbius's avatar
 
Jan Möbius committed
372 373 374 375 376 377 378 379 380 381
{
  if (projectionMode_ == ORTHOGRAPHIC_PROJECTION)
    projectionMode(PERSPECTIVE_PROJECTION);
  else
    projectionMode(ORTHOGRAPHIC_PROJECTION);

  updateGL();
}


Jan Möbius's avatar
 
Jan Möbius committed
382
void glViewer::projectionMode(ProjectionMode _p)
Jan Möbius's avatar
 
Jan Möbius committed
383 384
{
  if ((projectionMode_ = _p) == ORTHOGRAPHIC_PROJECTION)
385
    emit projectionModeChanged( true );
Jan Möbius's avatar
 
Jan Möbius committed
386
  else
387
    emit projectionModeChanged( false );
Jan Möbius's avatar
 
Jan Möbius committed
388 389

  updateProjectionMatrix();
390

391 392
  setCoordSysProjection(_p);

393
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
394 395
}

396 397 398
void glViewer::toggleNavigationMode()
{
  if (navigationMode_ == NORMAL_NAVIGATION)
Mike Kremer's avatar
Mike Kremer committed
399
    navigationMode(FIRSTPERSON_NAVIGATION);
400 401 402 403 404 405 406 407 408 409 410 411 412
  else
    navigationMode(NORMAL_NAVIGATION);
}


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

413 414 415 416 417 418 419 420 421 422 423
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
424

Jan Möbius's avatar
 
Jan Möbius committed
425
void glViewer::updateProjectionMatrix()
Jan Möbius's avatar
 
Jan Möbius committed
426 427 428 429 430 431 432 433
{
  if( projectionUpdateLocked_ )
    return;

  makeCurrent();

  glstate_->reset_projection();

434
  // In stereo mode we have to use a perspective matrix
Jan Möbius's avatar
Jan Möbius committed
435
  if (stereo_ || projectionMode_ == PERSPECTIVE_PROJECTION)
Jan Möbius's avatar
 
Jan Möbius committed
436
  {
437 438 439 440 441 442 443
    double aspect;

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

444 445 446 447
    // Get fovy
    double fovy = OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble();

    glstate_->perspective(fovy, (GLdouble) aspect,
448
                          properties_.nearPlane(), properties_.farPlane());
Jan Möbius's avatar
Jan Möbius committed
449 450 451 452
  }
  else
  {
    double aspect;
Jan Möbius's avatar
Jan Möbius committed
453

454
    if (isVisible() && glWidth() && glHeight())
Jan Möbius's avatar
Jan Möbius committed
455 456
      aspect = (double) glWidth() / (double) glHeight();
    else
457
      aspect = 1.0;
Jan Möbius's avatar
 
Jan Möbius committed
458

459 460 461
    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
462
  }
463

Jan Möbius's avatar
 
Jan Möbius committed
464 465 466 467 468 469
}


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


470
void glViewer::setScenePos(const ACG::Vec3d& _center, double _radius, const bool _resetTrackBall)
Jan Möbius's avatar
 
Jan Möbius committed
471
{
472
  if(_resetTrackBall) {
473
    properties_.trackballCenter(_center);
474 475
  }

476
  properties_.sceneCenter(_center);
477

478 479
  properties_.sceneRadius(_radius);
  properties_.trackballRadius(_radius);
480

481
  ACG::Vec3d c = glstate_->modelview().transform_point(properties_.sceneCenter());
482 483

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

486
  // Set near plane
487
  properties_.nearPlane( std::max(0.0001f * properties_.sceneRadius(),  -(c[2] + properties_.sceneRadius())) );
488
  
489 490 491 492
  updateProjectionMatrix();
  updateGL();

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


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


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

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

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

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

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

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

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

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

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

  updateGL();
}


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


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

//    makeCurrent();

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


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


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

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



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


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

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

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

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

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

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

  // draw mono or stereo
  makeCurrent();
607

Jan Möbius's avatar
Jan Möbius committed
608 609 610 611 612
  // Check if we use build in default renderers
  if ( renderManager().activeId( properties_.viewerId() ) == 0 ) {
    if (stereo_) drawScene_stereo();
    else         drawScene_mono();
  } else {
613
    renderManager().active( properties_.viewerId() )->plugin->render(glstate_,properties_);
Jan Möbius's avatar
Jan Möbius committed
614
  }
615
  
Jan Möbius's avatar
Jan Möbius committed
616 617
  if ( postProcessorManager().activeId( properties_.viewerId() ) != 0 ) {
    postProcessorManager().active( properties_.viewerId() )->plugin->postProcess(glstate_);
618
  }
619
  
Jan Möbius's avatar
 
Jan Möbius committed
620
  glFinish();
Jan Möbius's avatar
Jan Möbius committed
621

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

624 625 626
  
  // Inside the glWidget rendering, the system should not send extra updates
  properties_.blockSignals(false);
Jan Möbius's avatar
Jan Möbius committed
627

Jan Möbius's avatar
 
Jan Möbius committed
628 629 630 631 632 633
}


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


Jan Möbius's avatar
 
Jan Möbius committed
634
void glViewer::drawScene_mono()
Jan Möbius's avatar
 
Jan Möbius committed
635
{
636 637 638 639
  if (sceneGraphRoot_) {
    ViewObjectMarker *oM = properties_.objectMarker();
    GLuint refBits = 0;
    QSet<GLuint> references;
640

641 642 643
    if (oM)
    {
      glClear (GL_STENCIL_BUFFER_BIT);
644
      ACG::GLState::enable (GL_STENCIL_TEST);
645 646
      glStencilOp (GL_KEEP, GL_KEEP, GL_ZERO);
      glStencilFunc (GL_ALWAYS, 0, ~0);
647

648 649
      for (PluginFunctions::ObjectIterator o_it(PluginFunctions::ALL_OBJECTS, DATA_ALL) ;
          o_it != PluginFunctions::objectsEnd(); ++o_it)
650
      {
651 652 653 654
        bool ok;
        GLuint ref;

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

656
        if (ok)
657
        {
658 659 660 661
          o_it->stencilRefNode ()->setReference (ref);
          o_it->stencilRefNode ()->show ();
          refBits |= ref;
          references << ref;
662
        }
663 664
        else
          o_it->stencilRefNode ()->hide ();
665
      }
666 667 668 669
    }

    ACG::SceneGraph::DrawAction action( properties_.drawMode(), *glstate_ , false);
    ACG::SceneGraph::traverse_multipass(sceneGraphRoot_, action, *glstate_, properties_.drawMode() );
670

671 672 673 674 675
    if( blending_ )
    {
      ACG::SceneGraph::DrawAction action(properties_.drawMode(), *glstate_, true);
      ACG::SceneGraph::traverse_multipass(sceneGraphRoot_, action, *glstate_, properties_.drawMode());
    }
Jan Möbius's avatar
 
Jan Möbius committed
676

677 678 679
    if (oM)
    {
      if (oM->type() == ViewObjectMarker::PerBit)
Jan Möbius's avatar
 
Jan Möbius committed
680
      {
681 682 683 684
        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
685
      }
686

687
      glPushAttrib(GL_ALL_ATTRIB_BITS);
688

689
      ACG::GLState::enable(GL_BLEND);
690 691 692
      ACG::GLState::disable(GL_DEPTH_TEST);
      ACG::GLState::disable(GL_LIGHTING);
      ACG::GLState::disable(GL_DITHER);
693

694 695
      int vp_l, vp_b, vp_w, vp_h;
      glstate_->get_viewport (vp_l, vp_b, vp_w, vp_h);
696

697 698 699 700 701 702 703
      glMatrixMode(GL_PROJECTION);
      glPushMatrix ();
      glLoadIdentity();
      glOrtho(0, vp_w, vp_h, 0, 0, 1.0);
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix ();
      glLoadIdentity();
704

705
      glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
706

707 708 709 710 711 712 713
      foreach (unsigned int ref, references)
      {
        bool ok;
        GLenum sfactor;
        GLenum dfactor;
        ACG::Vec4f color;
        unsigned int mask = ~0;
714

715
        if (oM->type() == ViewObjectMarker::PerBit)
716
        {
717 718
          ok = oM->blendForStencilRefBit (ref, sfactor, dfactor, color);
          mask = ref;
719
        }
720 721
        else
          ok = oM->blendForStencilRefNumber (ref, sfactor, dfactor, color);
722

723 724
        if (!ok)
          continue;
725

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

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

731 732 733 734 735 736 737 738
        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
739

740 741 742 743
      glMatrixMode(GL_PROJECTION);
      glPopMatrix ();
      glMatrixMode(GL_MODELVIEW);
      glPopMatrix ();
Jan Möbius's avatar
 
Jan Möbius committed
744

745
      glPopAttrib ();
746
      ACG::GLState::disable (GL_STENCIL_TEST);
Jan Möbius's avatar
 
Jan Möbius committed
747
    }
748 749


Jan Möbius's avatar
 
Jan Möbius committed
750
  }
Jan Möbius's avatar
Jan Möbius committed
751

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
752 753 754 755 756 757 758 759 760 761 762
  if (cursorPainter_ && cursorPainter_->enabled () && cursorPositionValid_)
  {
    glstate_->push_modelview_matrix ();
    // reset view transformation
    glstate_->reset_modelview ();
    // translate cursor position to 0,0
    glstate_->translate (cursorPoint3D_[0], cursorPoint3D_[1], cursorPoint3D_[2]);
    // paint cursor
    cursorPainter_->paintCursor (glstate_);
    glstate_->pop_modelview_matrix ();
  }
763

Jan Möbius's avatar
 
Jan Möbius committed
764 765 766 767 768 769 770
}


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


void
Jan Möbius's avatar
 
Jan Möbius committed
771
glViewer::drawScene_stereo()
Jan Möbius's avatar
 
Jan Möbius committed
772
{
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
773 774 775 776 777 778 779 780 781 782 783 784 785
  if (OpenFlipper::Options::stereoMode () == OpenFlipper::Options::OpenGL && OpenFlipper::Options::glStereo ())
  {
    drawScene_glStereo ();
    return;
  }
  else if (OpenFlipper::Options::stereoMode () == OpenFlipper::Options::AnaglyphCustom && customAnaglyphSupported_)
  {
    drawScene_customAnaglyphStereo ();

    // if somthing went wrong, fallback to normal anaglyph
    if (customAnaglyphSupported_)
      return;
  }
786

Jan Möbius's avatar
Dennis:  
Jan Möbius committed
787 788
  drawScene_anaglyphStereo ();
}
Jan Möbius's avatar
 
Jan Möbius committed
789 790 791 792 793


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


Jan Möbius's avatar
 
Jan Möbius committed
794
void glViewer::setHome()
Jan Möbius's avatar
 
Jan Möbius committed
795 796 797
{
  home_modelview_          = glstate_->modelview();
  home_inverse_modelview_  = glstate_->inverse_modelview();
798
  homeOrthoWidth_          = properties_.orthoWidth();
799 800
  home_center_             = properties_.trackballCenter();
  home_radius_             = properties_.trackballRadius();
Jan Möbius's avatar
 
Jan Möbius committed
801 802 803
}


Jan Möbius's avatar
 
Jan Möbius committed
804
void glViewer::home()
Jan Möbius's avatar
 
Jan Möbius committed
805 806 807
{
  makeCurrent();
  glstate_->set_modelview(home_modelview_, home_inverse_modelview_);
808
  properties_.orthoWidth( homeOrthoWidth_ );
809 810
  properties_.trackballCenter( home_center_ );
  properties_.trackballRadius(home_radius_);
Jan Möbius's avatar
 
Jan Möbius committed
811 812
  updateProjectionMatrix();
  updateGL();
813

814
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
815 816 817 818 819 820 821

}


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


Jan Möbius's avatar
 
Jan Möbius committed
822
void glViewer::viewAll()
Jan Möbius's avatar
 
Jan Möbius committed
823
{
824
  makeCurrent();
Jan Möbius's avatar
 
Jan Möbius committed
825

826 827
  // 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
828

829 830 831
  // 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()));
832

833 834 835 836
  properties_.orthoWidth( 1.1 * properties_.sceneRadius() );
  double aspect = (double) glWidth() / (double) glHeight();
  if (aspect > 1.0)
    properties_.orthoWidth( aspect * properties_.orthoWidth() ) ;
837

838
  sceneGraph(PluginFunctions::getSceneGraphRootNode(), true);
839

840 841 842
  properties_.unLockUpdate();
  updateProjectionMatrix();
  updateGL();
843

844
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
845 846 847 848 849 850 851

}


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


Jan Möbius's avatar
 
Jan Möbius committed
852
void glViewer::setView(const ACG::GLMatrixd& _modelview,
Jan Möbius's avatar
 
Jan Möbius committed
853 854 855 856 857
			                  const ACG::GLMatrixd& _inverse_modelview)
{
  makeCurrent();
  glstate_->set_modelview(_modelview, _inverse_modelview);
  updateGL();
858

859
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
860 861 862 863 864 865
}


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


Jan Möbius's avatar
 
Jan Möbius committed
866
void glViewer::initializeGL()
Jan Möbius's avatar
 
Jan Möbius committed
867 868 869
{

  // lock update
870
  properties_.lockUpdate();
Jan Möbius's avatar
 
Jan Möbius committed
871 872 873 874 875

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

  // OpenGL state
876 877
  ACG::GLState::enable(GL_DEPTH_TEST);
  ACG::GLState::enable(GL_LIGHTING);
878
  ACG::GLState::disable(GL_DITHER);
879
  ACG::GLState::shadeModel( GL_FLAT );
Jan Möbius's avatar
 
Jan Möbius committed
880 881 882 883 884


  projectionMode(   projectionMode_   );
  normalsMode(      normalsMode_      );

885
  // Update all settings which would require a redraw
886
  applyProperties();
Jan Möbius's avatar
 
Jan Möbius committed
887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904

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

907 908 909 910
  customAnaglyphSupported_ = ACG::checkExtensionSupported("GL_ARB_fragment_program") &&
                            (ACG::checkExtensionSupported("GL_ARB_texture_rectangle") ||
                             ACG::checkExtensionSupported("GL_EXT_texture_rectangle") ||
                             ACG::checkExtensionSupported("GL_NV_texture_rectangle"));
911 912 913 914 915 916 917 918

  initialized_ = true;

  if (sceneGraphRoot_)
  {
    sceneGraph(sceneGraphRoot_, true);
    viewAll ();
  }
Jan Möbius's avatar
 
Jan Möbius committed
919 920 921 922 923 924
}


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


Jan Möbius's avatar
 
Jan Möbius committed
925
void glViewer::paintGL()
Jan Möbius's avatar
 
Jan Möbius committed
926
{
927 928
  if (!initialized_)
    initializeGL ();
Jan Möbius's avatar
 
Jan Möbius committed
929

930
  if (!properties_.updateLocked())
Jan Möbius's avatar
 
Jan Möbius committed
931
  {
Jan Möbius's avatar
Dennis:  
Jan Möbius committed
932 933
    ACG::Vec4f clear_color;

934
    properties_.lockUpdate();
Jan Möbius's avatar
 
Jan Möbius committed
935 936 937

    glPushAttrib (GL_ALL_ATTRIB_BITS);

938 939
    ACG::GLState::enable(GL_DEPTH_TEST);
    ACG::GLState::enable(GL_LIGHTING);
940
    ACG::GLState::disable(GL_DITHER);
941
    ACG::GLState::shadeModel( GL_FLAT );
Jan Möbius's avatar
 
Jan Möbius committed
942 943 944 945 946 947 948 949 950 951

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();


    normalsMode(      normalsMode_      );

952
    applyProperties();
953

954
    glstate_->setState();
Jan Möbius's avatar
 
Jan Möbius committed
955 956 957 958 959

    glColor4f(1.0,0.0,0.0,1.0);

    // clear (stereo mode clears buffers on its own)
    if (!stereo_)
Jan Möbius's avatar
 
Jan Möbius committed
960
      glstate_->clearBuffers ();
Jan Möbius's avatar
 
Jan Möbius committed
961

962
    properties_.unLockUpdate();
Jan Möbius's avatar
 
Jan Möbius committed
963 964 965 966 967 968 969 970 971 972 973

    // draw scene
    drawScene();

    glPopMatrix();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    glPopAttrib ();
  }
974

Jan Möbius's avatar
 
Jan Möbius committed
975 976 977 978 979 980
}


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


Jan Möbius's avatar
 
Jan Möbius committed
981
void glViewer::resizeEvent(QGraphicsSceneResizeEvent *)
Jan Möbius's avatar
 
Jan Möbius committed
982 983
{
  updateProjectionMatrix();
Jan Möbius's avatar
 
Jan Möbius committed
984
  glstate_->viewport(scenePos().x(),
Jan Möbius's avatar
Jan Möbius committed
985 986 987
                     scene()->height () - scenePos().y() - size().height (),
                     size().width (), size().height (),
                     scene()->width (), scene()->height ());
Jan Möbius's avatar
 
Jan Möbius committed
988
  update();
989

990
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
991 992
}

Jan Möbius's avatar
 
Jan Möbius committed
993 994 995
void glViewer::moveEvent (QGraphicsSceneMoveEvent *)
{
  glstate_->viewport(scenePos().x(),
Jan Möbius's avatar
Jan Möbius committed
996 997 998
                     scene()->height () - scenePos().y() - size().height (),
                     size().width (), size().height (),
                     scene()->width (), scene()->height ());
Jan Möbius's avatar
 
Jan Möbius committed
999
  update();
1000

1001
  emit viewChanged();
Jan Möbius's avatar
 
Jan Möbius committed
1002
}
Jan Möbius's avatar
 
Jan Möbius committed
1003 1004 1005

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

1006
void glViewer::encodeView(QString& _view, const QSize& _windowSize /*= QSize()*/, const int _splitterWidth /*=-1*/)
Jan Möbius's avatar
 
Jan Möbius committed
1007
{
1008
  // Get current matrices
Jan Möbius's avatar
 
Jan Möbius committed
1009 1010 1011
  const ACG::GLMatrixd m = glstate_->modelview();
  const ACG::GLMatrixd p = glstate_->projection();

1012
  // Add modelview matrix to output
1013
  _view += QString(COPY_PASTE_VIEW_START_STRING) + "\n";
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
  _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
1026
  _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
1027 1028 1029 1030 1031 1032
}


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


1033
bool glViewer::decodeView(const QString& _view, QSize *_windowSize /*= NULL*/, int* _splitterWidth /*= NULL*/)
Jan Möbius's avatar
 
Jan Möbius committed
1034
{
1035 1036 1037
  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
1038
    return false;
1039
  }
Jan Möbius's avatar
 
Jan Möbius committed
1040

1041 1042
  // Remove the magic from the string
  QString temp = _view;
1043
  temp.remove(0,sizeof(COPY_PASTE_VIEW_START_STRING));
Jan Möbius's avatar
 
Jan Möbius committed
1044

1045 1046
  //Split it into its components
  QStringList split = temp.split(QRegExp("[\\n\\s]"),QString::SkipEmptyParts);