Developer Documentation
QGLViewerWidget.cc
1 /* ========================================================================= *
2  * *
3  * OpenMesh *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openmesh.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenMesh. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40  * ========================================================================= */
41 
42 
43 
44 //== INCLUDES =================================================================
45 
46 #ifdef _MSC_VER
47 # pragma warning(disable: 4267 4311 4305)
48 #endif
49 
50 #include <iomanip>
51 #include <iostream>
52 #include <sstream>
53 #include <algorithm>
54 // --------------------
55 
56 // --------------------
57 #include <QApplication>
58 #include <QMenu>
59 #include <QCursor>
60 #include <QImage>
61 #include <QDateTime>
62 #include <QMouseEvent>
63 // --------------------
64 #include <OpenMesh/Apps/QtViewer/QGLViewerWidget.hh>
66 
67 #if !defined(M_PI)
68 # define M_PI 3.1415926535897932
69 #endif
70 
71 const double TRACKBALL_RADIUS = 0.6;
72 
73 
74 using namespace Qt;
75 using namespace OpenMesh;
76 
77 
78 //== IMPLEMENTATION ==========================================================
79 
80 std::string QGLViewerWidget::nomode_ = "";
81 
82 //----------------------------------------------------------------------------
83 
84 QGLViewerWidget::QGLViewerWidget( QWidget* _parent )
85  : QGLWidget( _parent )
86 {
87  init();
88 }
89 
90 //----------------------------------------------------------------------------
91 
92 QGLViewerWidget::
93 QGLViewerWidget( QGLFormat& _fmt, QWidget* _parent )
94  : QGLWidget( _fmt, _parent )
95 {
96  init();
97 }
98 
99 
100 //----------------------------------------------------------------------------
101 
102 void
103 QGLViewerWidget::init(void)
104 {
105  // qt stuff
106  setAttribute(Qt::WA_NoSystemBackground, true);
107  setFocusPolicy(Qt::StrongFocus);
108  setAcceptDrops( true );
109  setCursor(PointingHandCursor);
110 
111 
112  // popup menu
113 
114  popup_menu_ = new QMenu(this);
115  draw_modes_group_ = new QActionGroup(this);
116 
117  connect( draw_modes_group_, SIGNAL(triggered(QAction*)),
118  this, SLOT(slotDrawMode(QAction*)));
119 
120 
121  // init draw modes
122  n_draw_modes_ = 0;
123  //draw_mode_ = 3;
124  QAction *a;
125  a = add_draw_mode("Wireframe");
126  a->setShortcut(QKeySequence(Key_W));
127  add_draw_mode("Solid Flat");
128  a = add_draw_mode("Solid Smooth");
129  a->setShortcut(QKeySequence(Key_S));
130  a->setChecked(true);
131 
132  slotDrawMode(a);
133 }
134 
135 
136 //----------------------------------------------------------------------------
137 
138 QGLViewerWidget::~QGLViewerWidget()
139 {
140 }
141 
142 
143 //----------------------------------------------------------------------------
144 
145 void
146 QGLViewerWidget::setDefaultMaterial(void)
147 {
148  GLfloat mat_a[] = {0.1f, 0.1f, 0.1f, 1.0f};
149  GLfloat mat_d[] = {0.7f, 0.7f, 0.5f, 1.0f};
150  GLfloat mat_s[] = {1.0f, 1.0f, 1.0f, 1.0f};
151  GLfloat shine[] = {120.0f};
152 
153  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_a);
154  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_d);
155  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_s);
156  glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shine);
157 }
158 
159 
160 //----------------------------------------------------------------------------
161 
162 void
163 QGLViewerWidget::setDefaultLight(void)
164 {
165  GLfloat pos1[] = { 0.1f, 0.1f, -0.02f, 0.0f};
166  GLfloat pos2[] = {-0.1f, 0.1f, -0.02f, 0.0f};
167  GLfloat pos3[] = { 0.0f, 0.0f, 0.1f, 0.0f};
168  GLfloat col1[] = { 0.7f, 0.7f, 0.8f, 1.0f};
169  GLfloat col2[] = { 0.8f, 0.7f, 0.7f, 1.0f};
170  GLfloat col3[] = { 1.0f, 1.0f, 1.0f, 1.0f};
171 
172  glEnable(GL_LIGHT0);
173  glLightfv(GL_LIGHT0,GL_POSITION, pos1);
174  glLightfv(GL_LIGHT0,GL_DIFFUSE, col1);
175  glLightfv(GL_LIGHT0,GL_SPECULAR, col1);
176 
177  glEnable(GL_LIGHT1);
178  glLightfv(GL_LIGHT1,GL_POSITION, pos2);
179  glLightfv(GL_LIGHT1,GL_DIFFUSE, col2);
180  glLightfv(GL_LIGHT1,GL_SPECULAR, col2);
181 
182  glEnable(GL_LIGHT2);
183  glLightfv(GL_LIGHT2,GL_POSITION, pos3);
184  glLightfv(GL_LIGHT2,GL_DIFFUSE, col3);
185  glLightfv(GL_LIGHT2,GL_SPECULAR, col3);
186 }
187 
188 
189 //----------------------------------------------------------------------------
190 
191 
192 void
193 QGLViewerWidget::initializeGL()
194 {
195  // OpenGL state
196  glClearColor(0.0, 0.0, 0.0, 0.0);
197  glDisable( GL_DITHER );
198  glEnable( GL_DEPTH_TEST );
199 
200  // Material
201  setDefaultMaterial();
202 
203  // Lighting
204  glLoadIdentity();
205  setDefaultLight();
206 
207  // Fog
208  GLfloat fogColor[4] = { 0.3f, 0.3f, 0.4f, 1.0f };
209  glFogi(GL_FOG_MODE, GL_LINEAR);
210  glFogfv(GL_FOG_COLOR, fogColor);
211  glFogf(GL_FOG_DENSITY, 0.35f);
212  glHint(GL_FOG_HINT, GL_DONT_CARE);
213  glFogf(GL_FOG_START, 5.0f);
214  glFogf(GL_FOG_END, 25.0f);
215 
216  // scene pos and size
217  glMatrixMode(GL_MODELVIEW);
218  glLoadIdentity();
219  glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix_);
220  set_scene_pos(Vec3f(0.0, 0.0, 0.0), 1.0);
221 }
222 
223 
224 //----------------------------------------------------------------------------
225 
226 
227 void
228 QGLViewerWidget::resizeGL( int _w, int _h )
229 {
230  update_projection_matrix();
231  glViewport(0, 0, _w, _h);
232  updateGL();
233 }
234 
235 
236 //----------------------------------------------------------------------------
237 
238 
239 void
240 QGLViewerWidget::paintGL()
241 {
242  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
243  glMatrixMode( GL_PROJECTION );
244  glLoadMatrixd( projection_matrix_ );
245  glMatrixMode( GL_MODELVIEW );
246  glLoadMatrixd( modelview_matrix_ );
247 
248  if (draw_mode_)
249  {
250  assert(draw_mode_ <= n_draw_modes_);
251  draw_scene(draw_mode_names_[draw_mode_-1]);
252  }
253 }
254 
255 
256 //----------------------------------------------------------------------------
257 
258 
259 void
260 QGLViewerWidget::draw_scene(const std::string& _draw_mode)
261 {
262  if (_draw_mode == "Wireframe")
263  {
264  glDisable(GL_LIGHTING);
265  // glutWireTeapot(0.5);
266  }
267 
268  else if (_draw_mode == "Solid Flat")
269  {
270  glEnable(GL_LIGHTING);
271  glShadeModel(GL_FLAT);
272  //glutSolidTeapot(0.5);
273  }
274 
275  else if (_draw_mode == "Solid Smooth")
276  {
277  glEnable(GL_LIGHTING);
278  glShadeModel(GL_SMOOTH);
279  //glutSolidTeapot(0.5);
280  }
281 }
282 
283 
284 //----------------------------------------------------------------------------
285 
286 
287 void
288 QGLViewerWidget::mousePressEvent( QMouseEvent* _event )
289 {
290  // popup menu
291  if (_event->button() == RightButton && _event->buttons()== RightButton )
292  {
293  popup_menu_->exec(QCursor::pos());
294  }
295 
296  else
297  {
298  last_point_ok_ = map_to_sphere( last_point_2D_=_event->pos(),
299  last_point_3D_ );
300  }
301 }
302 
303 
304 //----------------------------------------------------------------------------
305 
306 
307 void
308 QGLViewerWidget::mouseMoveEvent( QMouseEvent* _event )
309 {
310  QPoint newPoint2D = _event->pos();
311 
312  // Left button: rotate around center_
313  // Middle button: translate object
314  // Left & middle button: zoom in/out
315 
316 
317  Vec3f newPoint3D;
318  bool newPoint_hitSphere = map_to_sphere( newPoint2D, newPoint3D );
319 
320  float dx = newPoint2D.x() - last_point_2D_.x();
321  float dy = newPoint2D.y() - last_point_2D_.y();
322 
323  float w = width();
324  float h = height();
325 
326 
327 
328  // enable GL context
329  makeCurrent();
330 
331 
332  // move in z direction
333  if ( (_event->buttons() == (LeftButton+MidButton)) ||
334  (_event->buttons() == LeftButton && _event->modifiers() == ControlModifier))
335  {
336  float value_y = radius_ * dy * 3.0 / h;
337  translate(Vec3f(0.0, 0.0, value_y));
338  }
339 
340 
341  // move in x,y direction
342  else if ( (_event->buttons() == MidButton) ||
343  (_event->buttons() == LeftButton && _event->modifiers() == AltModifier) )
344  {
345  float z = - (modelview_matrix_[ 2]*center_[0] +
346  modelview_matrix_[ 6]*center_[1] +
347  modelview_matrix_[10]*center_[2] +
348  modelview_matrix_[14]) /
349  (modelview_matrix_[ 3]*center_[0] +
350  modelview_matrix_[ 7]*center_[1] +
351  modelview_matrix_[11]*center_[2] +
352  modelview_matrix_[15]);
353 
354  float aspect = w / h;
355  float near_plane = 0.01 * radius_;
356  float top = tan(fovy()/2.0f*M_PI/180.0f) * near_plane;
357  float right = aspect*top;
358 
359  translate(Vec3f( 2.0*dx/w*right/near_plane*z,
360  -2.0*dy/h*top/near_plane*z,
361  0.0f));
362  }
363 
364 
365 
366  // rotate
367  else if (_event->buttons() == LeftButton) {
368 
369  if (last_point_ok_) {
370  if ((newPoint_hitSphere = map_to_sphere(newPoint2D, newPoint3D))) {
371  Vec3f axis = last_point_3D_ % newPoint3D;
372  if (axis.sqrnorm() < 1e-7) {
373  axis = Vec3f(1, 0, 0);
374  } else {
375  axis.normalize();
376  }
377  // find the amount of rotation
378  Vec3f d = last_point_3D_ - newPoint3D;
379  float t = 0.5 * d.norm() / TRACKBALL_RADIUS;
380  if (t < -1.0)
381  t = -1.0;
382  else if (t > 1.0)
383  t = 1.0;
384  float phi = 2.0 * asin(t);
385  float angle = phi * 180.0 / M_PI;
386  rotate(axis, angle);
387  }
388  }
389 
390  }
391 
392 
393  // remember this point
394  last_point_2D_ = newPoint2D;
395  last_point_3D_ = newPoint3D;
396  last_point_ok_ = newPoint_hitSphere;
397 
398  // trigger redraw
399  updateGL();
400 }
401 
402 
403 //----------------------------------------------------------------------------
404 
405 
406 void
407 QGLViewerWidget::mouseReleaseEvent( QMouseEvent* /* _event */ )
408 {
409  last_point_ok_ = false;
410 }
411 
412 
413 //-----------------------------------------------------------------------------
414 
415 
416 void QGLViewerWidget::wheelEvent(QWheelEvent* _event)
417 {
418  // Use the mouse wheel to zoom in/out
419 
420  float d = -(float)_event->delta() / 120.0 * 0.2 * radius_;
421  translate(Vec3f(0.0, 0.0, d));
422  updateGL();
423  _event->accept();
424 }
425 
426 
427 //----------------------------------------------------------------------------
428 
429 
430 void QGLViewerWidget::keyPressEvent( QKeyEvent* _event)
431 {
432  switch( _event->key() )
433  {
434  case Key_Print:
435  slotSnapshot();
436  break;
437 
438  case Key_H:
439  std::cout << "Keys:\n";
440  std::cout << " Print\tMake snapshot\n";
441  std::cout << " C\tenable/disable back face culling\n";
442  std::cout << " F\tenable/disable fog\n";
443  std::cout << " I\tDisplay information\n";
444  std::cout << " N\tenable/disable display of vertex normals\n";
445  std::cout << " Shift N\tenable/disable display of face normals\n";
446  std::cout << " Shift P\tperformance check\n";
447  break;
448 
449  case Key_C:
450  if ( glIsEnabled( GL_CULL_FACE ) )
451  {
452  glDisable( GL_CULL_FACE );
453  std::cout << "Back face culling: disabled\n";
454  }
455  else
456  {
457  glEnable( GL_CULL_FACE );
458  std::cout << "Back face culling: enabled\n";
459  }
460  updateGL();
461  break;
462 
463  case Key_F:
464  if ( glIsEnabled( GL_FOG ) )
465  {
466  glDisable( GL_FOG );
467  std::cout << "Fog: disabled\n";
468  }
469  else
470  {
471  glEnable( GL_FOG );
472  std::cout << "Fog: enabled\n";
473  }
474  updateGL();
475  break;
476 
477  case Key_I:
478  std::cout << "Scene radius: " << radius_ << std::endl;
479  std::cout << "Scene center: " << center_ << std::endl;
480  break;
481 
482  case Key_P:
483  if (_event->modifiers() & ShiftModifier)
484  {
485  double fps = performance();
486  std::cout << "fps: "
487  << std::setiosflags (std::ios_base::fixed)
488  << fps << std::endl;
489  }
490  break;
491 
492  case Key_Q:
493  case Key_Escape:
494  qApp->quit();
495  }
496  _event->ignore();
497 }
498 
499 
500 //----------------------------------------------------------------------------
501 
502 
503 void
504 QGLViewerWidget::translate( const OpenMesh::Vec3f& _trans )
505 {
506  // Translate the object by _trans
507  // Update modelview_matrix_
508  makeCurrent();
509  glLoadIdentity();
510  glTranslated( _trans[0], _trans[1], _trans[2] );
511  glMultMatrixd( modelview_matrix_ );
512  glGetDoublev( GL_MODELVIEW_MATRIX, modelview_matrix_);
513 }
514 
515 
516 //----------------------------------------------------------------------------
517 
518 
519 void
520 QGLViewerWidget::rotate( const OpenMesh::Vec3f& _axis, float _angle )
521 {
522  // Rotate around center center_, axis _axis, by angle _angle
523  // Update modelview_matrix_
524 
525  Vec3f t( modelview_matrix_[0]*center_[0] +
526  modelview_matrix_[4]*center_[1] +
527  modelview_matrix_[8]*center_[2] +
528  modelview_matrix_[12],
529  modelview_matrix_[1]*center_[0] +
530  modelview_matrix_[5]*center_[1] +
531  modelview_matrix_[9]*center_[2] +
532  modelview_matrix_[13],
533  modelview_matrix_[2]*center_[0] +
534  modelview_matrix_[6]*center_[1] +
535  modelview_matrix_[10]*center_[2] +
536  modelview_matrix_[14] );
537 
538  makeCurrent();
539  glLoadIdentity();
540  glTranslatef(t[0], t[1], t[2]);
541  glRotated( _angle, _axis[0], _axis[1], _axis[2]);
542  glTranslatef(-t[0], -t[1], -t[2]);
543  glMultMatrixd(modelview_matrix_);
544  glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix_);
545 }
546 
547 
548 //----------------------------------------------------------------------------
549 
550 
551 bool
552 QGLViewerWidget::map_to_sphere( const QPoint& _v2D, OpenMesh::Vec3f& _v3D )
553 {
554  // This is actually doing the Sphere/Hyperbolic sheet hybrid thing,
555  // based on Ken Shoemake's ArcBall in Graphics Gems IV, 1993.
556  double x = (2.0*_v2D.x() - width())/width();
557  double y = -(2.0*_v2D.y() - height())/height();
558  double xval = x;
559  double yval = y;
560  double x2y2 = xval*xval + yval*yval;
561 
562  const double rsqr = TRACKBALL_RADIUS*TRACKBALL_RADIUS;
563  _v3D[0] = xval;
564  _v3D[1] = yval;
565  if (x2y2 < 0.5*rsqr) {
566  _v3D[2] = sqrt(rsqr - x2y2);
567  } else {
568  _v3D[2] = 0.5*rsqr/sqrt(x2y2);
569  }
570 
571  return true;
572  }
573 
574 
575 //----------------------------------------------------------------------------
576 
577 
578 void
579 QGLViewerWidget::update_projection_matrix()
580 {
581  makeCurrent();
582  glMatrixMode( GL_PROJECTION );
583  glLoadIdentity();
584 
585  const double fovY = 45.0;
586  const double aspect = static_cast<double>(width()) / static_cast<double>(height());
587  const double zNear = 0.01*radius_;
588  const double zFar = 100.0*radius_;
589 
590 // Replacement for: gluPerspective(45.0, (GLfloat) width() / (GLfloat) height(), 0.01*radius_, 100.0*radius_);
591  const double pi = 3.1415926535897932384626433832795;
592  const double fH = tan( fovY / 360 * pi ) * zNear;
593  const double fW = fH * aspect;
594  glFrustum( -fW, fW, -fH, fH, zNear, zFar );
595 
596 
597  glGetDoublev( GL_PROJECTION_MATRIX, projection_matrix_);
598  glMatrixMode( GL_MODELVIEW );
599 }
600 
601 
602 //----------------------------------------------------------------------------
603 
604 
605 void
606 QGLViewerWidget::view_all()
607 {
608  translate( Vec3f( -(modelview_matrix_[0]*center_[0] +
609  modelview_matrix_[4]*center_[1] +
610  modelview_matrix_[8]*center_[2] +
611  modelview_matrix_[12]),
612  -(modelview_matrix_[1]*center_[0] +
613  modelview_matrix_[5]*center_[1] +
614  modelview_matrix_[9]*center_[2] +
615  modelview_matrix_[13]),
616  -(modelview_matrix_[2]*center_[0] +
617  modelview_matrix_[6]*center_[1] +
618  modelview_matrix_[10]*center_[2] +
619  modelview_matrix_[14] +
620  3.0*radius_) ) );
621 }
622 
623 
624 //----------------------------------------------------------------------------
625 
626 
627 void
628 QGLViewerWidget::set_scene_pos( const OpenMesh::Vec3f& _cog, float _radius )
629 {
630  center_ = _cog;
631  radius_ = _radius;
632  glFogf( GL_FOG_START, 1.5*_radius );
633  glFogf( GL_FOG_END, 3.0*_radius );
634 
635  update_projection_matrix();
636  view_all();
637 }
638 
639 
640 //----------------------------------------------------------------------------
641 
642 
643 QAction*
644 QGLViewerWidget::add_draw_mode(const std::string& _s)
645 {
646  ++n_draw_modes_;
647  draw_mode_names_.push_back(_s);
648 
649  QActionGroup *grp = draw_modes_group_;
650  QAction* act = new QAction(tr(_s.c_str()), this);
651  act->setCheckable(true);
652  act->setData(n_draw_modes_);
653 
654  grp->addAction(act);
655  popup_menu_->addAction(act);
656  addAction(act, _s.c_str());
657 
658  return act;
659 }
660 
661 void QGLViewerWidget::addAction(QAction* act, const char * name)
662 {
663  names_to_actions[name] = act;
664  Super::addAction(act);
665 }
666 void QGLViewerWidget::removeAction(QAction* act)
667 {
668  ActionMap::iterator it = names_to_actions.begin(), e = names_to_actions.end();
669  ActionMap::iterator found = e;
670  for(; it!=e; ++it) {
671  if (it->second == act) {
672  found = it;
673  break;
674  }
675  }
676  if (found != e) {
677  names_to_actions.erase(found);
678 }
679  popup_menu_->removeAction(act);
680  draw_modes_group_->removeAction(act);
681  Super::removeAction(act);
682 }
683 
684 void QGLViewerWidget::removeAction(const char* name)
685 {
686  QString namestr = QString(name);
687  ActionMap::iterator e = names_to_actions.end();
688 
689  ActionMap::iterator found = names_to_actions.find(namestr);
690  if (found != e) {
691  removeAction(found->second);
692  }
693 }
694 
695 QAction* QGLViewerWidget::findAction(const char* name)
696 {
697  QString namestr = QString(name);
698  ActionMap::iterator e = names_to_actions.end();
699 
700  ActionMap::iterator found = names_to_actions.find(namestr);
701  if (found != e) {
702  return found->second;
703  }
704  return 0;
705 }
706 
707 //----------------------------------------------------------------------------
708 
709 
710 void
711 QGLViewerWidget::del_draw_mode(const std::string& _s)
712 {
713  QString cmp = _s.c_str();
714  QList<QAction*> actions_ = popup_menu_->actions();
715  QList<QAction*>::iterator it=actions_.begin(), e=actions_.end();
716  for(; it!=e; ++it) {
717  if ((*it)->text() == cmp) { break; }
718  }
719 
720 #if _DEBUG
721  assert( it != e );
722 #else
723  if ( it == e )
724  return;
725 #endif
726 
727  popup_menu_->removeAction(*it);
728  //QActionGroup *grp = draw_modes_group_;
729 
730 }
731 
732 
733 //----------------------------------------------------------------------------
734 
735 
736 void
737 QGLViewerWidget::slotDrawMode(QAction* _mode)
738 {
739  // save draw mode
740  draw_mode_ = _mode->data().toInt();
741  updateGL();
742 
743  // check selected draw mode
744  //popup_menu_->setItemChecked(draw_mode_, true);
745 }
746 
747 
748 //----------------------------------------------------------------------------
749 
750 
751 double
752 QGLViewerWidget::performance()
753 {
754  setCursor( Qt::WaitCursor );
755 
756  double fps(0.0);
757 
758  makeCurrent();
759  glMatrixMode(GL_MODELVIEW);
760  glPushMatrix();
761 
763 
764  unsigned int frames = 60;
765  const float angle = 360.0/(float)frames;
766  unsigned int i;
767  Vec3f axis;
768 
769  glFinish();
770 
771  timer.start();
772  for (i=0, axis=Vec3f(1,0,0); i<frames; ++i)
773  { rotate(axis, angle); paintGL(); swapBuffers(); }
774  timer.stop();
775 
776  qApp->processEvents();
777 
778  timer.cont();
779  for (i=0, axis=Vec3f(0,1,0); i<frames; ++i)
780  { rotate(axis, angle); paintGL(); swapBuffers(); }
781  timer.stop();
782 
783  qApp->processEvents();
784 
785  timer.cont();
786  for (i=0, axis=Vec3f(0,0,1); i<frames; ++i)
787  { rotate(axis, angle); paintGL(); swapBuffers(); }
788  timer.stop();
789 
790  glFinish();
791  timer.stop();
792 
793  glPopMatrix();
794  updateGL();
795 
796  fps = ( (3.0 * frames) / timer.seconds() );
797 
798  setCursor( PointingHandCursor );
799 
800  return fps;
801 }
802 
803 
804 void
805 QGLViewerWidget::slotSnapshot( void )
806 {
807  QImage image;
808  size_t w(width()), h(height());
809  GLenum buffer( GL_BACK );
810 
811  try
812  {
813  image = QImage(w, h, QImage::Format_RGB32);
814 
815  std::vector<GLubyte> fbuffer(3*w*h);
816 
817  qApp->processEvents();
818  makeCurrent();
819  updateGL();
820  glFinish();
821 
822  glReadBuffer( buffer );
823  glPixelStorei(GL_PACK_ALIGNMENT, 1);
824  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
825  paintGL();
826  glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, &fbuffer[0] );
827 
828  unsigned int x,y,offset;
829 
830  for (y=0; y<h; ++y) {
831  for (x=0; x<w; ++x) {
832  offset = 3*(y*w + x);
833  image.setPixel(x, h-y-1, qRgb(fbuffer[offset],
834  fbuffer[offset+1],
835  fbuffer[offset+2]));
836  }
837  }
838 
839 
840  QString name = "snapshot-";
841 #if defined(_MSC_VER)
842  {
843  std::stringstream s;
844  QDateTime dt = QDateTime::currentDateTime();
845  s << dt.date().year()
846  << std::setw(2) << std::setfill('0') << dt.date().month()
847  << std::setw(2) << std::setfill('0') << dt.date().day()
848  << std::setw(2) << std::setfill('0') << dt.time().hour()
849  << std::setw(2) << std::setfill('0') << dt.time().minute()
850  << std::setw(2) << std::setfill('0') << dt.time().second();
851  name += QString(s.str().c_str());
852  }
853 #else
854  name += QDateTime::currentDateTime().toString( "yyMMddhhmmss" );
855 #endif
856  name += ".png";
857 
858  image.save( name, "PNG");
859  }
860  catch( std::bad_alloc& )
861  {
862  qWarning("Mem Alloc Error");
863  }
864 
865 }
866 
867 
868 
869 //=============================================================================
QAction * add_draw_mode(const std::string &_s)
add draw mode to popup menu, and return the QAction created
void del_draw_mode(const std::string &_s)
delete draw mode from popup menu
virtual void draw_scene(const std::string &_draw_mode) override
inherited drawing method
T angle(T _cos_angle, T _sin_angle)
Definition: MathDefs.hh:140
double seconds(void) const
Returns measured time in seconds, if the timer is in state &#39;Stopped&#39;.
void stop(void)
Stop measurement.
void cont(void)
Continue measurement.
void rotate(const ACG::Vec3d &_axis, const double _angle, const ACG::Vec3d &_center, int _viewer)
Rotate Scene around axis.
auto norm() const -> decltype(std::sqrt(std::declval< VectorT< S, DIM >>().sqrnorm()))
compute euclidean norm
Definition: Vector11T.hh:414
decltype(std::declval< S >() *std::declval< S >()) sqrnorm() const
compute squared euclidean norm
Definition: Vector11T.hh:402
void translate(const ACG::Vec3d &_vector, int _viewer)
Translate viewer pos by given vector.
void start(void)
Start measurement.
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:434