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);
Jan Möbius's avatar
 
Jan Möbius committed
1047
1048

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

1051
  // Check if the number of components matches the expected size
1052
  if ( split.size() != 37 ) {
1053
1054
1055
    std::cerr << "Unable to paste view ... wrong parameter count!! is" <<  split.size()  << std::endl;
    return false;
  }
1056
  //////////////////
1057
  // Parse the components
1058
1059
  // first, get the projection and the modelview matrices
  for (std::size_t i = 0; i < 4; ++i)
1060
  {
1061
    for (std::size_t j = 0; j < 4; ++j)
1062
    {
1063
1064
      m(i,j) = split[i*4 + j].toDouble();
      p(i,j) = split[i*4 + j +16].toDouble();
1065
    }
1066
  }
1067

1068
1069
1070
1071
1072
1073
  //parse the window size if requested
  if (_windowSize)
  {
    //restore the old window size
    int w =  split[32].toInt();
    int h =  split[33].toInt();
1074
1075
    *_windowSize = QSize(w,h);
  }
1076
1077
  //parse the splitter width if requested
  if (_splitterWidth)
1078
  {
1079
    *_splitterWidth = split[34].toInt();
1080
1081
  }

1082
1083
1084

  pMode =  split[35].toInt();
  properties_.orthoWidth( split[36].toDouble() );
1085
1086

  // Switch to our gl context
Jan Möbius's avatar
 
Jan Möbius committed
1087
1088
  makeCurrent();

1089
  // set projection mode
Jan Möbius's avatar
 
Jan Möbius committed
1090
1091
1092
  if (projectionMode_ != (ProjectionMode)pMode)
    projectionMode((ProjectionMode)pMode);

1093
  // Apply new modelview matrix
Jan Möbius's avatar
 
Jan Möbius committed
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
  glstate_->set_modelview(m);

  updateGL();

  return true;
}


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


1105
void glViewer::actionCopyView(const QSize &_windowSize /*= QSize(-1,-1)*/, const int _splitterWidth /*= -1*/)
1106
{
1107
  QString view;
1108
  encodeView(view,_windowSize,_splitterWidth);
1109
1110
1111
1112
1113
1114
1115
  QApplication::clipboard()->setText(view);
}


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


1116
void glViewer::actionPasteView(QSize * _windowSize /*= NULL*/, int *_splitterWidth /*= NULL*/)
1117
{
1118
1119
  QString view;
  view = QApplication::clipboard()->text();
1120
  decodeView(view,_windowSize,_splitterWidth);
1121
1122
1123
}


Jan Möbius's avatar
 
Jan Möbius committed
1124
1125
1126
//-----------------------------------------------------------------------------

void