Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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