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>
65 #include <OpenMesh/Tools/Utils/Timer.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
762 OpenMesh::Utils::Timer timer;
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 //=============================================================================
QGLViewerWidget::add_draw_mode
QAction * add_draw_mode(const std::string &_s)
add draw mode to popup menu, and return the QAction created
Definition: QGLViewerWidget.cc:644
QGLViewerWidget::del_draw_mode
void del_draw_mode(const std::string &_s)
delete draw mode from popup menu
Definition: QGLViewerWidget.cc:711
MeshViewerWidgetT::draw_scene
virtual void draw_scene(const std::string &_draw_mode) override
inherited drawing method
Definition: MeshViewerWidgetT_impl.hh:572
OpenMesh::angle
T angle(T _cos_angle, T _sin_angle)
Definition: MathDefs.hh:140
OpenMesh::VectorT< float, 3 >
OpenMesh::Utils::Timer::seconds
double seconds(void) const
Returns measured time in seconds, if the timer is in state &#39;Stopped&#39;.
OpenMesh::Utils::Timer::stop
void stop(void)
Stop measurement.
OpenMesh::Utils::Timer::cont
void cont(void)
Continue measurement.
OpenMesh
Definition: MeshItems.hh:59
PluginFunctions::rotate
void rotate(const ACG::Vec3d &_axis, const double _angle, const ACG::Vec3d &_center, int _viewer)
Rotate Scene around axis.
Definition: PluginFunctions.cc:835
OpenMesh::VectorT::norm
auto norm() const -> decltype(std::sqrt(std::declval< VectorT< S, DIM >>().sqrnorm()))
compute euclidean norm
Definition: Vector11T.hh:414
Timer.hh
Qt
OpenMesh::VectorT::sqrnorm
decltype(std::declval< S >() *std::declval< S >()) sqrnorm() const
compute squared euclidean norm
Definition: Vector11T.hh:402
PluginFunctions::translate
void translate(const ACG::Vec3d &_vector, int _viewer)
Translate viewer pos by given vector.
Definition: PluginFunctions.cc:823
OpenMesh::Utils::Timer::start
void start(void)
Start measurement.
OpenMesh::Utils::Timer
Definition: Timer.hh:82
OpenMesh::VectorT::normalize
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:434