QtBaseViewer.cc 67.3 KB
Newer Older
Jan Möbius's avatar
Jan Möbius committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*===========================================================================*\
*                                                                            *
*                              OpenFlipper                                   *
*      Copyright (C) 2001-2010 by Computer Graphics Group, RWTH Aachen       *
*                           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
60
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/QtWidgets/QtWheel.hh>
#include <ACG/Scenegraph/DrawModes.hh>
#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 <QFileDialog>
#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>

Jan Möbius's avatar
   
Jan Möbius committed
124
125
126
127
128
129
130
131
132
133
134
135
//== NAMESPACES ===============================================================



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

static const char          VIEW_MAGIC[] =
  "ACG::QtWidgets::QGLViewerWidget encoded view";

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


136
glViewer::glViewer( QGraphicsScene* _scene,
137
                    QGLWidget* _glWidget,
138
                    Viewer::ViewerProperties& _properties,
139
                    QGraphicsWidget* _parent) :
Jan Möbius's avatar
   
Jan Möbius committed
140
  QGraphicsWidget(_parent),
Jan Möbius's avatar
   
Jan Möbius committed
141
142
143
  glareaGrabbed_(false),
  projectionUpdateLocked_(false),
  blending_(true),
Jan Möbius's avatar
   
Jan Möbius committed
144
145
  glScene_(_scene),
  glWidget_(_glWidget),
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
146
147
  cursorPainter_(0),
  cursorPositionValid_(false),
148
149
  pProgram_(0),
  philipsStereoInitialized_(false),
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
156
  glstate_(0),
  initialized_(false)
Jan Möbius's avatar
   
Jan Möbius committed
157
158
159
{

  // widget stuff
160
  createWidgets();
Jan Möbius's avatar
   
Jan Möbius committed
161
162
163

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

Jan Möbius's avatar
   
Jan Möbius committed
166
167
  // state
  isRotating_       = false;
Mike Kremer's avatar
Mike Kremer committed
168
  lookAround_       = false;
Jan Möbius's avatar
   
Jan Möbius committed
169
170
171

  sceneGraphRoot_   = 0;

172
  normalsMode_      = NORMALIZE_NORMALS;
Jan Möbius's avatar
   
Jan Möbius committed
173
  projectionMode_   = PERSPECTIVE_PROJECTION;
Jan Möbius's avatar
Jan Möbius committed
174
  navigationMode_   = NORMAL_NAVIGATION;
175

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

193
194
195
196
197
198
199
  // 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
200
201
202
  connect( &properties_,SIGNAL(updated()), this, SLOT( slotPropertiesUpdated() ) );


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

Jan Möbius's avatar
   
Jan Möbius committed
206
  setAcceptDrops(true);
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
207

208
  setHome();
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
209
210
211
212
213
214
215
216

  // initialize custom anaglyph stereo
  agTexWidth_ = 0;
  agTexHeight_ = 0;
  agTexture_[0] = 0;
  agTexture_[1] = 0;
  agProgram_ = 0;
  customAnaglyphSupported_ = false;
217
218
219

  clickTimer_.setSingleShot (true);
  connect (&clickTimer_, SIGNAL(timeout ()), this, SLOT(slotClickTimeout ()));
Jan Möbius's avatar
   
Jan Möbius committed
220
221
222
223
224
225
}


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


Jan Möbius's avatar
   
Jan Möbius committed
226
glViewer::~glViewer()
Jan Möbius's avatar
   
Jan Möbius committed
227
{
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
228
  finiCustomAnaglyphStereo ();
Jan Möbius's avatar
   
Jan Möbius committed
229
230
231
232
233
234
235
236
  delete glstate_;
}


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


QSize
Jan Möbius's avatar
   
Jan Möbius committed
237
glViewer::sizeHint() const
Jan Möbius's avatar
   
Jan Möbius committed
238
239
240
241
242
243
244
{
  return QSize( 600, 600 );
}

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


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

Jan Möbius's avatar
   
Jan Möbius committed
249
void glViewer::swapBuffers() {
Jan Möbius's avatar
   
Jan Möbius committed
250
251
252
253
254
255
256
  glWidget_->swapBuffers();
}


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


257
void glViewer::sceneGraph(ACG::SceneGraph::BaseNode* _root, const bool _resetTrackBall)
Jan Möbius's avatar
   
Jan Möbius committed
258
259
260
{
  sceneGraphRoot_ = _root;

Jan Möbius's avatar
Jan Möbius committed
261
  if (sceneGraphRoot_ )
Jan Möbius's avatar
   
Jan Möbius committed
262
  {
Jan Möbius's avatar
Jan Möbius committed
263
264
265
266
267
268
269
270
    
    // 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
271
    // get scene size
Jan Möbius's avatar
Jan Möbius committed
272
    // Single pass action, as the bounding box is not influenced by multipass traversal
Jan Möbius's avatar
   
Jan Möbius committed
273
274
275
276
277
    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
278
279
    
    
Jan Möbius's avatar
   
Jan Möbius committed
280
281
282

    if ( ( bbmin[0] > bbmax[0] ) ||
         ( bbmin[1] > bbmax[1] ) ||
283
284
285
         ( bbmin[2] > bbmax[2] )   ) {
      
      // Invalid bounding box, try to recover
286
      setScenePos( ACG::Vec3d( 0.0,0.0,0.0 ) , 1.0, _resetTrackBall );
287
288
289
290
    
      // 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
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
    } else {
      
      // For small scenes, we set the scene radius to 10
      // otherwise we take the real radius
      if ( ( bbmax - bbmin ).max() < 10.0 )  {
        setScenePos( ( bbmin + bbmax )        * 0.5,
                     10.0,
                     _resetTrackBall);
                   
      } else {
        setScenePos( ( bbmin + bbmax )        * 0.5,
                     ( bbmax - bbmin ).norm() * 0.5,
                     _resetTrackBall); 
      }
                   
    }
307
308
309
310
                   
    // remember the new bounding box for the state
    glstate_->set_bounding_box(bbmin,bbmax);
    
Jan Möbius's avatar
   
Jan Möbius committed
311
  }
312
  
Jan Möbius's avatar
   
Jan Möbius committed
313
314
315
316
317
318
319
320
321
322

  updateGL();

  emit(signalSceneGraphChanged(sceneGraphRoot_));
}


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


Jan Möbius's avatar
   
Jan Möbius committed
323
void glViewer::trackMouse(bool _track)
Jan Möbius's avatar
   
Jan Möbius committed
324
325
326
327
328
329
330
{
  trackMouse_ = _track;
}


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

Jan Möbius's avatar
   
Jan Möbius committed
331
void glViewer::perspectiveProjection()
Jan Möbius's avatar
   
Jan Möbius committed
332
333
334
335
336
337
{
  projectionMode(PERSPECTIVE_PROJECTION);
  updateGL();
}


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


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

  updateGL();
}


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

  updateProjectionMatrix();
364

365
  emit viewChanged();
Jan Möbius's avatar
   
Jan Möbius committed
366
367
}

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


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

385
386
387
388
389
390
391
392
393
394
395
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
396

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

  makeCurrent();

  glstate_->reset_projection();

406
  // In stereo mode we have to use a perspective matrix
Jan Möbius's avatar
Jan Möbius committed
407
  if (stereo_ || projectionMode_ == PERSPECTIVE_PROJECTION)
Jan Möbius's avatar
   
Jan Möbius committed
408
  {
409
410
411
412
413
414
415
    double aspect;

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

416
417
418
419
    // Get fovy
    double fovy = OpenFlipperSettings().value("Core/Projection/FOVY", 45.0).toDouble();

    glstate_->perspective(fovy, (GLdouble) aspect,
420
                          properties_.nearPlane(), properties_.farPlane());
Jan Möbius's avatar
Jan Möbius committed
421
422
423
424
  }
  else
  {
    double aspect;
Jan Möbius's avatar
Jan Möbius committed
425

426
    if (isVisible() && glWidth() && glHeight())
Jan Möbius's avatar
Jan Möbius committed
427
428
      aspect = (double) glWidth() / (double) glHeight();
    else
429
      aspect = 1.0;
Jan Möbius's avatar
   
Jan Möbius committed
430

431
432
433
    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
434
  }
435

Jan Möbius's avatar
   
Jan Möbius committed
436
437
438
439
440
441
}


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


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

448
  properties_.sceneCenter(_center);
449

450
451
  properties_.sceneRadius(_radius);
  properties_.trackballRadius(_radius);
452

453
  ACG::Vec3d c = glstate_->modelview().transform_point(properties_.sceneCenter());
454
455

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

458
  // Set near plane
459
  properties_.nearPlane( std::max(0.0001f * properties_.sceneRadius(),  -(c[2] + properties_.sceneRadius())) );
460
  
461
462
463
464
  updateProjectionMatrix();
  updateGL();

  emit viewChanged();
465
466
467
468
469
470
}


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


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

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

479
  emit viewChanged();
Jan Möbius's avatar
   
Jan Möbius committed
480
481
}

482
483
484
485
486
487
488
//-----------------------------------------------------------------------------

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

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

Jan Möbius's avatar
   
Jan Möbius committed
497
void glViewer::normalsMode(NormalsMode _mode)
Jan Möbius's avatar
   
Jan Möbius committed
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
{
  makeCurrent();

  switch(normalsMode_ = _mode)
  {
    case DONT_TOUCH_NORMALS:
      glDisable(GL_NORMALIZE);
      break;

    case NORMALIZE_NORMALS:
      glEnable(GL_NORMALIZE);
      break;
  }

  updateGL();
}


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


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

//    qApp->processEvents();
//    makeCurrent();

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


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


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

    emit viewUpdated();
Jan Möbius's avatar
   
Jan Möbius committed
544
545
546
547
548
549
550
551
  }
}



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


Jan Möbius's avatar
   
Jan Möbius committed
552
void glViewer::drawScene()
Jan Möbius's avatar
   
Jan Möbius committed
553
554
555
556
557
{
  QTime  timer;
  timer.start();


Jan Möbius's avatar
   
Jan Möbius committed
558
559
560
561
  // *****************************************************************
  // Adjust clipping planes
  // *****************************************************************
  // Far plane
562
  ACG::Vec3d c = glstate_->modelview().transform_point(properties_.sceneCenter());
Jan Möbius's avatar
   
Jan Möbius committed
563
564

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

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

Jan Möbius's avatar
   
Jan Möbius committed
570
571
572
573
574
575
576
577
578
579
580
581
  updateProjectionMatrix();

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

  // draw mono or stereo
  makeCurrent();
  if (stereo_) drawScene_stereo();
  else         drawScene_mono();

  glFinish();
  frame_time_ = timer.elapsed();
Jan Möbius's avatar
Jan Möbius committed
582
583


Jan Möbius's avatar
   
Jan Möbius committed
584
585
586
587
588
589
}


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


Jan Möbius's avatar
   
Jan Möbius committed
590
void glViewer::drawScene_mono()
Jan Möbius's avatar
   
Jan Möbius committed
591
592
593
{
  if (sceneGraphRoot_)
  {
594
    if (! properties_.renderPicking() ) {
595

Jan Möbius's avatar
Jan Möbius committed
596
      ViewObjectMarker *oM = properties_.objectMarker();
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
      GLuint refBits = 0;
      QSet<GLuint> references;

      if (oM)
      {
        glClear (GL_STENCIL_BUFFER_BIT);
        glEnable (GL_STENCIL_TEST);
        glStencilOp (GL_KEEP, GL_KEEP, GL_ZERO);
        glStencilFunc (GL_ALWAYS, 0, ~0);

        for (PluginFunctions::ObjectIterator o_it(PluginFunctions::ALL_OBJECTS, DATA_ALL) ;
                                             o_it != PluginFunctions::objectsEnd(); ++o_it)
        {
          bool ok;
          GLuint ref;

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

          if (ok)
          {
            o_it->stencilRefNode ()->setReference (ref);
            o_it->stencilRefNode ()->show ();
            refBits |= ref;
            references << ref;
          }
          else
            o_it->stencilRefNode ()->hide ();
        }
      }

627
      ACG::SceneGraph::DrawAction action( properties_.drawMode(), *glstate_ , false);
628
      ACG::SceneGraph::traverse_multipass(sceneGraphRoot_, action, *glstate_, properties_.drawMode() );
Jan Möbius's avatar
   
Jan Möbius committed
629
630
631

      if( blending_ )
      {
632
        ACG::SceneGraph::DrawAction action(properties_.drawMode(), *glstate_, true);
633
        ACG::SceneGraph::traverse_multipass(sceneGraphRoot_, action, *glstate_, properties_.drawMode());
Jan Möbius's avatar
   
Jan Möbius committed
634
      }
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706

      if (oM)
      {
        if (oM->type() == ViewObjectMarker::PerBit)
        {
          references.clear ();
          for (unsigned int i = 0; i < sizeof (GLuint) * 8; i++)
            if (refBits & (1 << i))
              references << (1 << i);
        }

        glPushAttrib(GL_ALL_ATTRIB_BITS);

        glEnable(GL_BLEND);
        glDisable(GL_DEPTH_TEST);
        glDisable(GL_LIGHTING);
        glDisable(GL_DITHER);

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

        glMatrixMode(GL_PROJECTION);
        glPushMatrix ();
        glLoadIdentity();
        glOrtho(0, vp_w, vp_h, 0, 0, 1.0);
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix ();
        glLoadIdentity();

        glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);

        foreach (unsigned int ref, references)
        {
          bool ok;
          GLenum sfactor;
          GLenum dfactor;
          ACG::Vec4f color;
          unsigned int mask = ~0;

          if (oM->type() == ViewObjectMarker::PerBit)
          {
            ok = oM->blendForStencilRefBit (ref, sfactor, dfactor, color);
            mask = ref;
          }
          else
            ok = oM->blendForStencilRefNumber (ref, sfactor, dfactor, color);

          if (!ok)
            continue;

          glStencilFunc (GL_EQUAL, ref, mask);

          glBlendFunc (sfactor, dfactor);
          glColor4f (color[0], color [1], color [2], color[3]);

          glBegin (GL_QUADS);
          glVertex2i(0, 0);
          glVertex2i(0, vp_h);
          glVertex2i(vp_w, vp_h);
          glVertex2i(vp_w, 0);
          glEnd ();

        }

        glMatrixMode(GL_PROJECTION);
        glPopMatrix ();
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix ();

        glPopAttrib ();
        glDisable (GL_STENCIL_TEST);
      }
Jan Möbius's avatar
   
Jan Möbius committed
707
708
709
710
711
712
    } else {

      // prepare GL state
      makeCurrent();

      glDisable(GL_LIGHTING);
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
713
      glDisable(GL_BLEND);
Jan Möbius's avatar
   
Jan Möbius committed
714
715
716
717
718
      glClear(GL_DEPTH_BUFFER_BIT);
      glInitNames();
      glPushName((GLuint) 0);

      // do the picking
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
719
      glstate_->pick_init (true);
Jan Möbius's avatar
Jan Möbius committed
720
      ACG::SceneGraph::PickAction action(*glstate_, properties_.renderPickingMode(), properties_.drawMode());
721
      ACG::SceneGraph::traverse_multipass(sceneGraphRoot_, action,*glstate_);
Jan Möbius's avatar
   
Jan Möbius committed
722
723

      glEnable(GL_LIGHTING);
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
724
      glEnable(GL_BLEND);
Jan Möbius's avatar
   
Jan Möbius committed
725
726
    }
  }
Jan Möbius's avatar
Jan Möbius committed
727

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
728
729
730
731
732
733
734
735
736
737
738
  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 ();
  }
Jan Möbius's avatar
   
Jan Möbius committed
739
740
741
742
743
744
745
}


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


void
Jan Möbius's avatar
   
Jan Möbius committed
746
glViewer::drawScene_stereo()
Jan Möbius's avatar
   
Jan Möbius committed
747
{
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
748
749
750
751
752
753
754
755
756
757
758
759
  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;
760
761
762
  } else if (OpenFlipper::Options::stereoMode () == OpenFlipper::Options::Philips )
  {
    drawScenePhilipsStereo ();
763

764
    return;
765

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
766
  }
767
768


Jan Möbius's avatar
   
Jan Möbius committed
769

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
770
771
  drawScene_anaglyphStereo ();
}
Jan Möbius's avatar
   
Jan Möbius committed
772
773
774
775
776


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


Jan Möbius's avatar
   
Jan Möbius committed
777
void glViewer::setHome()
Jan Möbius's avatar
   
Jan Möbius committed
778
779
780
{
  home_modelview_          = glstate_->modelview();
  home_inverse_modelview_  = glstate_->inverse_modelview();
781
  homeOrthoWidth_          = properties_.orthoWidth();
782
783
  home_center_             = properties_.trackballCenter();
  home_radius_             = properties_.trackballRadius();
Jan Möbius's avatar
   
Jan Möbius committed
784
785
786
}


Jan Möbius's avatar
   
Jan Möbius committed
787
void glViewer::home()
Jan Möbius's avatar
   
Jan Möbius committed
788
789
790
{
  makeCurrent();
  glstate_->set_modelview(home_modelview_, home_inverse_modelview_);
791
  properties_.orthoWidth( homeOrthoWidth_ );
792
793
  properties_.trackballCenter( home_center_ );
  properties_.trackballRadius(home_radius_);
Jan Möbius's avatar
   
Jan Möbius committed
794
795
  updateProjectionMatrix();
  updateGL();
796

797
  emit viewChanged();
Jan Möbius's avatar
   
Jan Möbius committed
798
799
800
801
802
803
804

}


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


Jan Möbius's avatar
   
Jan Möbius committed
805
void glViewer::viewAll()
Jan Möbius's avatar
   
Jan Möbius committed
806
{
807
  makeCurrent();
Jan Möbius's avatar
   
Jan Möbius committed
808

809
810
  // 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
811

812
813
814
  // 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()));
815

816
817
818
819
  properties_.orthoWidth( 1.1 * properties_.sceneRadius() );
  double aspect = (double) glWidth() / (double) glHeight();
  if (aspect > 1.0)
    properties_.orthoWidth( aspect * properties_.orthoWidth() ) ;
820

821
  sceneGraph(PluginFunctions::getSceneGraphRootNode(), true);
822

823
824
825
  properties_.unLockUpdate();
  updateProjectionMatrix();
  updateGL();
826

827
  emit viewChanged();
Jan Möbius's avatar
   
Jan Möbius committed
828
829
830
831
832
833
834

}


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


Jan Möbius's avatar
   
Jan Möbius committed
835
void glViewer::flyTo(const QPoint& _pos, bool _move_back)
Jan Möbius's avatar
   
Jan Möbius committed
836
837
838
839
840
841
842
843
844
845
{
  makeCurrent();

  unsigned int nodeIdx, targetIdx;
  ACG::Vec3d hitPoint;

  if (pick( ACG::SceneGraph::PICK_ANYTHING, _pos, nodeIdx, targetIdx, &hitPoint))
  {
    if (projectionMode_ == PERSPECTIVE_PROJECTION)
    {
846
      ACG::Vec3d eye(glstate_->eye());
Jan Möbius's avatar
   
Jan Möbius committed
847
848
849
850
851
852
      ACG::Vec3d t = hitPoint - eye;
      ACG::Vec3d e = eye + t * (_move_back ? -0.5f : 0.5f);
      flyTo(e, hitPoint, 300);
    }
    else
    {
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871

      // Project hitpoint to get depth
      ACG::Vec3d hitPointProjected = glstate_->project(hitPoint);

      // Create projected center point with same depth as hitpoint
      ACG::Vec3d centerPointProjected = hitPointProjected;
      centerPointProjected[0] = glstate_->viewport_width() / 2.0 ;
      centerPointProjected[1] = glstate_->viewport_height() / 2.0 ;

      // unproject center point
      ACG::Vec3d centerPointUnProjected = glstate_->unproject(centerPointProjected);
      
      // translation vector to make hitpoint project to center point (both need same depth)
      ACG::Vec3d t = hitPoint - centerPointUnProjected;

      // Transform to correct translation vector with modelview.
      t = glstate_->modelview().transform_vector(t);
      
      // originalWidth 
872
      double orthoWidthOriginal = properties_.orthoWidth();
Jan Möbius's avatar
   
Jan Möbius committed
873
874
875

      // Set the double click point as the new trackball center
      // Rotations will use this point as the center.
876
      properties_.trackballCenter( hitPoint );
877
878
879
880
881
882
883
884
885
886
887
888
889
890
      
      // how many frames in _time ms ?
      unsigned int  frames = (unsigned int)(300 / frame_time_);
      if (frames > 1000) frames=1000;
      
      // animate it
      if (frames > 10)
      {
        
        for (unsigned int i=1; i<frames; ++i)
        {
          // zoom back one frame 
          if ( _move_back ) {
            // Move back by factor 2
891
            properties_.orthoWidth( orthoWidthOriginal * (1.0 + 1.0 / (double)frames * i ) );
892
893
          } else
            // Move forward with factor 0.5
894
            properties_.orthoWidth( orthoWidthOriginal * (1.0 - 0.5 / (double)frames * i ) );
895
896
897
898
899
900
901
902
903
904
905
906
907
908
          
          // apply translation
          translate(t * (- 1.0 / (double)frames  ) );
          
          update();
          qApp->processEvents();
        }
        updatePickCache_ = true;
      } else {
        
        // direct translation
        translate(-t);
        
        // set the zoom factor when no animation is performed
909
910
911
912
        if ( _move_back )
          properties_.orthoWidth( properties_.orthoWidth() * 2.0 );
        else
          properties_.orthoWidth(properties_.orthoWidth() * -0.5);
913
914
        
      }
Jan Möbius's avatar
   
Jan Möbius committed
915
916
917
918
919
920

      // Update the projection matrix
      updateProjectionMatrix();

      // Redraw scene
      updateGL();
921

922
      emit viewChanged();
Jan Möbius's avatar
   
Jan Möbius committed
923
924
    }

Jan Möbius's avatar
Jan Möbius committed
925

Jan Möbius's avatar
   
Jan Möbius committed
926
927
928
929
  }
}


Jan Möbius's avatar
   
Jan Möbius committed
930
void glViewer::flyTo(const ACG::Vec3d&  _position,
Jan Möbius's avatar
   
Jan Möbius committed
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
			 const ACG::Vec3d&  _center,
			 double        _time)
{
  makeCurrent();

  // compute rotation
  ACG::Vec3d c = glstate_->modelview().transform_point(_center);
  ACG::Vec3d p = glstate_->modelview().transform_point(_position);
  ACG::Vec3d view =(p-c).normalize();
  ACG::Vec3d z(0,0,1);
  ACG::Vec3d axis = (z % -view).normalize();
  double angle = acos(std::max(-1.0,
			      std::min(1.0,
				       (z | view)))) / M_PI * 180.0;

  if (angle > 175)
    axis  = ACG::Vec3d(0,1,0);


  // compute translation
  ACG::Vec3d target = glstate_->modelview().transform_point(_center);
  ACG::Vec3d trans ( -target[0],
		-target[1],
		-target[2] - (_position-_center).norm() );



  // how many frames in _time ms ?
  unsigned int  frames = (unsigned int)(_time / frame_time_);
  if (frames > 1000) frames=1000;




  // animate it
  if (frames > 10)
  {
    ACG::Vec3d t = trans / (double)frames;
    double a = angle / (double)frames;

    for (unsigned int i=0; i<frames; ++i)
    {
      translate(t);
      if (fabs(a) > FLT_MIN)
	     rotate(axis, a, _center);

Jan Möbius's avatar
   
Jan Möbius committed
977
978
      update();
      qApp->processEvents();
Jan Möbius's avatar
   
Jan Möbius committed
979
    }
980
    updatePickCache_ = true;
Jan Möbius's avatar
   
Jan Möbius committed
981
982
983
984
985
986
987
988
989
990
991
992
993
994
  }


  // no animation
  else
  {
    translate(trans);
    if (fabs(angle) > FLT_MIN)
      rotate(axis, angle, _center);

    updateGL();
  }


995
996
  properties_.trackballCenter( _center );
  properties_.trackballRadius( std::max( properties_.sceneRadius(),( _center - _position ).norm() * 0.9f  ) );
Jan Möbius's avatar
   
Jan Möbius committed
997
998
999
1000
1001
1002
}


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


Jan Möbius's avatar
   
Jan Möbius committed
1003
void glViewer::setView(const ACG::GLMatrixd& _modelview,
Jan Möbius's avatar
   
Jan Möbius committed
1004
1005
1006
1007
1008
			                  const ACG::GLMatrixd& _inverse_modelview)
{
  makeCurrent();
  glstate_->set_modelview(_modelview, _inverse_modelview);
  updateGL();
1009

1010
  emit viewChanged();
Jan Möbius's avatar
   
Jan Möbius committed
1011
1012
1013
1014
1015
1016
}


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


Jan Möbius's avatar
   
Jan Möbius committed
1017
void glViewer::initializeGL()
Jan Möbius's avatar
   
Jan Möbius committed
1018
1019
1020
{

  // lock update
1021
  properties_.lockUpdate();
Jan Möbius's avatar
   
Jan Möbius committed
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035

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

  // OpenGL state
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_LIGHTING);
  glDisable(GL_DITHER);
  glShadeModel( GL_FLAT );


  projectionMode(   projectionMode_   );
  normalsMode(      normalsMode_      );

1036
  // Update all settings which would require a redraw
1037
  applyProperties();
Jan Möbius's avatar
   
Jan Möbius committed
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055

  // 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)
1056
  properties_.unLockUpdate();
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
1057
1058
1059
1060
1061

  customAnaglyphSupported_ = glewIsSupported("GL_ARB_fragment_program") &&
      (glewIsSupported("GL_ARB_texture_rectangle") ||
       glewIsSupported("GL_EXT_texture_rectangle") ||
       glewIsSupported("GL_NV_texture_rectangle"));
1062
1063
1064
1065
1066
1067
1068
1069

  initialized_ = true;

  if (sceneGraphRoot_)
  {
    sceneGraph(sceneGraphRoot_, true);
    viewAll ();
  }
Jan Möbius's avatar
   
Jan Möbius committed
1070
1071
1072
1073
1074
1075
}


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


Jan Möbius's avatar
   
Jan Möbius committed
1076
void glViewer::paintGL()
Jan Möbius's avatar
   
Jan Möbius committed
1077
{
1078
1079
  if (!initialized_)
    initializeGL ();
Jan Möbius's avatar
   
Jan Möbius committed
1080

1081
  if (!properties_.updateLocked())
Jan Möbius's avatar
   
Jan Möbius committed
1082
  {
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
1083
1084
    ACG::Vec4f clear_color;

1085
    properties_.lockUpdate();
Jan Möbius's avatar
   
Jan Möbius committed
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102

    glPushAttrib (GL_ALL_ATTRIB_BITS);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glDisable(GL_DITHER);
    glShadeModel( GL_FLAT );

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();


    normalsMode(      normalsMode_      );

1103
    applyProperties();
1104

Jan Möbius's avatar
   
Jan Möbius committed
1105
1106
1107
1108
    glstate_->setState ();

    glColor4f(1.0,0.0,0.0,1.0);

Jan Möbius's avatar
Dennis:    
Jan Möbius committed
1109
1110
1111
1112
1113
1114
    if (properties_.renderPicking())
    {
      clear_color = properties_.glState().clear_color();
      properties_.glState().set_clear_color (ACG::Vec4f (0.0, 0.0, 0.0, 1.0));
    }

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

1119
    properties_.unLockUpdate();
Jan Möbius's avatar
   
Jan Möbius committed
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129

    // draw scene
    drawScene();

    glPopMatrix();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    glPopAttrib ();
Jan Möbius's avatar
Dennis:    
Jan Möbius committed
1130
1131
1132

    if (properties_.renderPicking())
      properties_.glState().set_clear_color (clear_color);
Jan Möbius's avatar
   
Jan Möbius committed
1133
1134
1135
1136
1137
1138
1139
  }
}


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


Jan Möbius's avatar
   
Jan Möbius committed
1140
void glViewer::resizeEvent(QGraphicsSceneResizeEvent *)
Jan Möbius's avatar
   
Jan Möbius committed
1141
1142
{
  updateProjectionMatrix();
Jan Möbius's avatar
   
Jan Möbius committed
1143
  glstate_->viewport(scenePos().x(),
Jan Möbius's avatar
Jan Möbius committed
1144
1145
1146
                     scene()->height () - scenePos().y() - size().height (),
                     size().width (), size().height (),
                     scene()->width (), scene()->height ());
Jan Möbius's avatar
   
Jan Möbius committed
1147
  update();
1148

1149
  emit viewChanged();
Jan Möbius's avatar
   
Jan Möbius committed
1150
1151
}

Jan Möbius's avatar
   
Jan Möbius committed
1152
1153
1154
void glViewer::moveEvent (QGraphicsSceneMoveEvent *)
{
  glstate_->viewport(scenePos().x(),
Jan Möbius's avatar
Jan Möbius committed
1155
1156
1157
                     scene()->height () - scenePos().y() - size().height (),
                     size().width (), size().height (),
                     scene()->width (), scene()->height ());
Jan Möbius's avatar
   
Jan Möbius committed
1158
  update();
1159

1160
  emit viewChanged();
Jan Möbius's avatar
   
Jan Möbius committed
1161
}
Jan Möbius's avatar
   
Jan Möbius committed
1162
1163
1164

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

Jan Möbius's avatar
   
Jan Möbius committed
1165
void glViewer::encodeView(QString& _view)
Jan Möbius's avatar
   
Jan Möbius committed
1166
{
1167
  // Get current matrices
Jan Möbius's avatar
   
Jan Möbius committed
1168
1169
1170
  const ACG::GLMatrixd m = glstate_->modelview();
  const ACG::GLMatrixd p = glstate_->projection();

1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
  // Add modelview matrix to output
  _view += QString(VIEW_MAGIC) + "\n";
  _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
1185
  _view += QString::number(glWidth()) + " " +  QString::number(glHeight()) + " " + QString::number(projectionMode_) + " " + QString::number(properties_.orthoWidth()) + "\n";
Jan Möbius's avatar
   
Jan Möbius committed
1186
1187
1188
1189
1190
1191
}


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


Jan Möbius's avatar
   
Jan Möbius committed
1192
bool glViewer::decodeView(const QString& _view)
Jan Möbius's avatar
   
Jan Möbius committed
1193
1194
1195
1196
{
  if (_view.left(sizeof(VIEW_MAGIC)-1) != QString(VIEW_MAGIC))
    return false;

1197
1198
1199
  // Remove the magic from the string
  QString temp = _view;
  temp.remove(0,sizeof(VIEW_MAGIC));
Jan Möbius's avatar
   
Jan Möbius committed
1200

1201
1202
  //Split it into its components
  QStringList split = temp.split(QRegExp("[\\n\\s]"),QString::SkipEmptyParts);
Jan Möbius's avatar
   
Jan Möbius committed
1203
1204
1205
1206

  ACG::GLMatrixd m, p;
  int            w, h, pMode;

1207
1208
1209
1210
1211
  // Check if the number of components matches the expected size
  if ( split.size() != 36 ) {
    std::cerr << "Unable to paste view ... wrong parameter count!! is" <<  split.size()  << std::endl;
    return false;
  }
Jan Möbius's avatar
   
Jan Möbius committed
1212

1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
  // Parse the components
  bool ok = true;;

  m(0,0) = split[0].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  m(0,1) = split[1].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  m(0,2) = split[2].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  m(0,3) = split[3].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  m(1,0) = split[4].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  m(1,1) = split[5].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  m(1,2) = split[6].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  m(1,3) = split[7].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  m(2,0) = split[8].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  m(2,1) = split[9].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  m(2,2) = split[10].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  m(2,3) = split[11].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  m(3,0) = split[12].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  m(3,1) = split[13].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  m(3,2) = split[14].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  m(3,3) = split[15].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(0,0) = split[16].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(0,1) = split[17].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(0,2) = split[18].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(0,3) = split[19].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(1,0) = split[20].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(1,1) = split[21].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(1,2) = split[22].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(1,3) = split[23].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(2,0) = split[24].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(2,1) = split[25].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(2,2) = split[26].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(2,3) = split[27].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(3,0) = split[28].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(3,1) = split[29].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(3,2) = split[30].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  p(3,3) = split[31].toDouble(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }

  w =  split[32].toInt(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  h =  split[33].toInt(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
  pMode =  split[34].toInt(&ok); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
1252
  properties_.orthoWidth( split[35].toDouble(&ok) ); if ( !ok ) { std::cerr << "Error in decoding View!" << std::endl; return false; }
1253
1254

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

1257
  // set projection mode
Jan Möbius's avatar
   
Jan Möbius committed
1258
1259
1260
  if (projectionMode_ != (ProjectionMode)pMode)
    projectionMode((ProjectionMode)pMode);

1261
  // Apply new modelview matrix
Jan Möbius's avatar
   
Jan Möbius committed
1262
1263
1264
  glstate_->set_modelview(m);


1265
1266
1267
1268
1269
1270
1271
1272
1273
  std::cerr << "Todo : Add Checkbox if size should also be pasted" << std::endl;

//   if (w>0 && h>0 &&
//       action_["PasteDropSize"]->isChecked() )
//   {
//     glstate_->set_projection(p);
//     glView_->setFixedSize(w,h);
//     updateGeometry();
//   }
Jan Möbius's avatar
   
Jan Möbius committed
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283

  updateGL();

  return true;
}


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


Jan Möbius's avatar
   
Jan Möbius committed
1284
void glViewer::actionCopyView()
1285
1286
1287
1288
1289
1290
1291
1292
1293
{
  QString view; encodeView(view);
  QApplication::clipboard()->setText(view);
}


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


Jan Möbius's avatar
   
Jan Möbius committed
1294
void glViewer::actionPasteView()
1295
1296
1297
1298
1299
1300
{
  QString view; view=QApplication::clipboard()->text();
  decodeView(view);
}


Jan Möbius's avatar
   
Jan Möbius committed
1301
1302
1303
//-----------------------------------------------------------------------------

void
1304
glViewer::createWidgets()
Jan Möbius's avatar
   
Jan Möbius committed
1305
1306
{
  // Construct GL context & widget