47# pragma warning(disable: 4267 4311 4305)
57#include <QApplication>
63#include <QActionGroup>
65#include <OpenMesh/Apps/QtViewer/QGLViewerWidget.hh>
69# define M_PI 3.1415926535897932
72#if QT_VERSION_MAJOR > 5
76const double TRACKBALL_RADIUS = 0.6;
85std::string QGLViewerWidget::nomode_ =
"";
89#if QT_VERSION_MAJOR < 6
90QGLViewerWidget::QGLViewerWidget( QWidget* _parent ) : QGLWidget( _parent )
100#if QT_VERSION_MAJOR > 5
101void QGLViewerWidget::updateGL() {
109QGLViewerWidget::init(
void)
112 setAttribute(Qt::WA_NoSystemBackground,
true);
113 setFocusPolicy(Qt::StrongFocus);
114 setAcceptDrops(
true );
115 setCursor(PointingHandCursor);
120 popup_menu_ =
new QMenu(
this);
121 draw_modes_group_ =
new QActionGroup(
this);
123 connect( draw_modes_group_, SIGNAL(triggered(QAction*)),
124 this, SLOT(slotDrawMode(QAction*)));
132 a->setShortcut(QKeySequence(Key_W));
135 a->setShortcut(QKeySequence(Key_S));
144QGLViewerWidget::~QGLViewerWidget()
152QGLViewerWidget::setDefaultMaterial(
void)
154 GLfloat mat_a[] = {0.1f, 0.1f, 0.1f, 1.0f};
155 GLfloat mat_d[] = {0.7f, 0.7f, 0.5f, 1.0f};
156 GLfloat mat_s[] = {1.0f, 1.0f, 1.0f, 1.0f};
157 GLfloat shine[] = {120.0f};
159 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_a);
160 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_d);
161 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_s);
162 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shine);
169QGLViewerWidget::setDefaultLight(
void)
171 GLfloat pos1[] = { 0.1f, 0.1f, -0.02f, 0.0f};
172 GLfloat pos2[] = {-0.1f, 0.1f, -0.02f, 0.0f};
173 GLfloat pos3[] = { 0.0f, 0.0f, 0.1f, 0.0f};
174 GLfloat col1[] = { 0.7f, 0.7f, 0.8f, 1.0f};
175 GLfloat col2[] = { 0.8f, 0.7f, 0.7f, 1.0f};
176 GLfloat col3[] = { 1.0f, 1.0f, 1.0f, 1.0f};
179 glLightfv(GL_LIGHT0,GL_POSITION, pos1);
180 glLightfv(GL_LIGHT0,GL_DIFFUSE, col1);
181 glLightfv(GL_LIGHT0,GL_SPECULAR, col1);
184 glLightfv(GL_LIGHT1,GL_POSITION, pos2);
185 glLightfv(GL_LIGHT1,GL_DIFFUSE, col2);
186 glLightfv(GL_LIGHT1,GL_SPECULAR, col2);
189 glLightfv(GL_LIGHT2,GL_POSITION, pos3);
190 glLightfv(GL_LIGHT2,GL_DIFFUSE, col3);
191 glLightfv(GL_LIGHT2,GL_SPECULAR, col3);
199QGLViewerWidget::initializeGL()
202 glClearColor(0.0, 0.0, 0.0, 0.0);
203 glDisable( GL_DITHER );
204 glEnable( GL_DEPTH_TEST );
207 setDefaultMaterial();
214 GLfloat fogColor[4] = { 0.3f, 0.3f, 0.4f, 1.0f };
215 glFogi(GL_FOG_MODE, GL_LINEAR);
216 glFogfv(GL_FOG_COLOR, fogColor);
217 glFogf(GL_FOG_DENSITY, 0.35f);
218 glHint(GL_FOG_HINT, GL_DONT_CARE);
219 glFogf(GL_FOG_START, 5.0f);
220 glFogf(GL_FOG_END, 25.0f);
223 glMatrixMode(GL_MODELVIEW);
225 glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix_);
226 set_scene_pos(
Vec3f(0.0, 0.0, 0.0), 1.0);
234QGLViewerWidget::resizeGL(
int _w,
int _h )
236 update_projection_matrix();
237 glViewport(0, 0, _w, _h);
246QGLViewerWidget::paintGL()
248 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
249 glMatrixMode( GL_PROJECTION );
250 glLoadMatrixd( projection_matrix_ );
251 glMatrixMode( GL_MODELVIEW );
252 glLoadMatrixd( modelview_matrix_ );
256 assert(draw_mode_ <= n_draw_modes_);
257 draw_scene(draw_mode_names_[draw_mode_-1]);
266QGLViewerWidget::draw_scene(
const std::string& _draw_mode)
268 if (_draw_mode ==
"Wireframe")
270 glDisable(GL_LIGHTING);
274 else if (_draw_mode ==
"Solid Flat")
276 glEnable(GL_LIGHTING);
277 glShadeModel(GL_FLAT);
281 else if (_draw_mode ==
"Solid Smooth")
283 glEnable(GL_LIGHTING);
284 glShadeModel(GL_SMOOTH);
294QGLViewerWidget::mousePressEvent( QMouseEvent* _event )
297 if (_event->button() == RightButton && _event->buttons()== RightButton )
299 popup_menu_->exec(QCursor::pos());
304 last_point_ok_ = map_to_sphere( last_point_2D_=_event->pos(),
314QGLViewerWidget::mouseMoveEvent( QMouseEvent* _event )
316 QPoint newPoint2D = _event->pos();
324 bool newPoint_hitSphere = map_to_sphere( newPoint2D, newPoint3D );
326 float dx = newPoint2D.x() - last_point_2D_.x();
327 float dy = newPoint2D.y() - last_point_2D_.y();
339 if ( (_event->buttons() == (LeftButton|MiddleButton)) ||
340 (_event->buttons() == LeftButton && _event->modifiers() == ControlModifier))
342 float value_y = radius_ * dy * 3.0 / h;
343 translate(
Vec3f(0.0, 0.0, value_y));
348 else if ( (_event->buttons() == MiddleButton) ||
349 (_event->buttons() == LeftButton && _event->modifiers() == AltModifier) )
351 float z = - (modelview_matrix_[ 2]*center_[0] +
352 modelview_matrix_[ 6]*center_[1] +
353 modelview_matrix_[10]*center_[2] +
354 modelview_matrix_[14]) /
355 (modelview_matrix_[ 3]*center_[0] +
356 modelview_matrix_[ 7]*center_[1] +
357 modelview_matrix_[11]*center_[2] +
358 modelview_matrix_[15]);
360 float aspect = w / h;
361 float near_plane = 0.01 * radius_;
362 float top = tan(fovy()/2.0f*M_PI/180.0f) * near_plane;
363 float right = aspect*top;
365 translate(
Vec3f( 2.0*dx/w*right/near_plane*z,
366 -2.0*dy/h*top/near_plane*z,
373 else if (_event->buttons() == LeftButton) {
375 if (last_point_ok_) {
376 if ((newPoint_hitSphere = map_to_sphere(newPoint2D, newPoint3D))) {
377 Vec3f axis = last_point_3D_ % newPoint3D;
379 axis =
Vec3f(1, 0, 0);
384 Vec3f d = last_point_3D_ - newPoint3D;
385 float t = 0.5 * d.
norm() / TRACKBALL_RADIUS;
390 float phi = 2.0 * asin(t);
391 float angle = phi * 180.0 / M_PI;
400 last_point_2D_ = newPoint2D;
401 last_point_3D_ = newPoint3D;
402 last_point_ok_ = newPoint_hitSphere;
413QGLViewerWidget::mouseReleaseEvent( QMouseEvent* )
415 last_point_ok_ =
false;
422void QGLViewerWidget::wheelEvent(QWheelEvent* _event)
426 float d = -(float)( _event->angleDelta().y() / 120.0 * 0.2 * radius_ );
427 translate(
Vec3f(0.0, 0.0, d));
436void QGLViewerWidget::keyPressEvent( QKeyEvent* _event)
438 switch( _event->key() )
445 std::cout <<
"Keys:\n";
446 std::cout <<
" Print\tMake snapshot\n";
447 std::cout <<
" C\tenable/disable back face culling\n";
448 std::cout <<
" F\tenable/disable fog\n";
449 std::cout <<
" I\tDisplay information\n";
450 std::cout <<
" N\tenable/disable display of vertex normals\n";
451 std::cout <<
" Shift N\tenable/disable display of face normals\n";
452 std::cout <<
" Shift P\tperformance check\n";
456 if ( glIsEnabled( GL_CULL_FACE ) )
458 glDisable( GL_CULL_FACE );
459 std::cout <<
"Back face culling: disabled\n";
463 glEnable( GL_CULL_FACE );
464 std::cout <<
"Back face culling: enabled\n";
470 if ( glIsEnabled( GL_FOG ) )
473 std::cout <<
"Fog: disabled\n";
478 std::cout <<
"Fog: enabled\n";
484 std::cout <<
"Scene radius: " << radius_ << std::endl;
485 std::cout <<
"Scene center: " << center_ << std::endl;
489 if (_event->modifiers() & ShiftModifier)
491 double fps = performance();
493 << std::setiosflags (std::ios_base::fixed)
516 glTranslated( _trans[0], _trans[1], _trans[2] );
517 glMultMatrixd( modelview_matrix_ );
518 glGetDoublev( GL_MODELVIEW_MATRIX, modelview_matrix_);
531 Vec3f t( modelview_matrix_[0]*center_[0] +
532 modelview_matrix_[4]*center_[1] +
533 modelview_matrix_[8]*center_[2] +
534 modelview_matrix_[12],
535 modelview_matrix_[1]*center_[0] +
536 modelview_matrix_[5]*center_[1] +
537 modelview_matrix_[9]*center_[2] +
538 modelview_matrix_[13],
539 modelview_matrix_[2]*center_[0] +
540 modelview_matrix_[6]*center_[1] +
541 modelview_matrix_[10]*center_[2] +
542 modelview_matrix_[14] );
546 glTranslatef(t[0], t[1], t[2]);
547 glRotated( _angle, _axis[0], _axis[1], _axis[2]);
548 glTranslatef(-t[0], -t[1], -t[2]);
549 glMultMatrixd(modelview_matrix_);
550 glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix_);
558QGLViewerWidget::map_to_sphere(
const QPoint& _v2D,
OpenMesh::Vec3f& _v3D )
562 double x = (2.0*_v2D.x() - width())/width();
563 double y = -(2.0*_v2D.y() - height())/height();
566 double x2y2 = xval*xval + yval*yval;
568 const double rsqr = TRACKBALL_RADIUS*TRACKBALL_RADIUS;
571 if (x2y2 < 0.5*rsqr) {
572 _v3D[2] = sqrt(rsqr - x2y2);
574 _v3D[2] = 0.5*rsqr/sqrt(x2y2);
585QGLViewerWidget::update_projection_matrix()
588 glMatrixMode( GL_PROJECTION );
591 const double fovY = 45.0;
592 const double aspect =
static_cast<double>(width()) /
static_cast<double>(height());
593 const double zNear = 0.01*radius_;
594 const double zFar = 100.0*radius_;
597 const double pi = 3.1415926535897932384626433832795;
598 const double fH = tan( fovY / 360 * pi ) * zNear;
599 const double fW = fH * aspect;
600 glFrustum( -fW, fW, -fH, fH, zNear, zFar );
603 glGetDoublev( GL_PROJECTION_MATRIX, projection_matrix_);
604 glMatrixMode( GL_MODELVIEW );
612QGLViewerWidget::view_all()
614 translate(
Vec3f( -(modelview_matrix_[0]*center_[0] +
615 modelview_matrix_[4]*center_[1] +
616 modelview_matrix_[8]*center_[2] +
617 modelview_matrix_[12]),
618 -(modelview_matrix_[1]*center_[0] +
619 modelview_matrix_[5]*center_[1] +
620 modelview_matrix_[9]*center_[2] +
621 modelview_matrix_[13]),
622 -(modelview_matrix_[2]*center_[0] +
623 modelview_matrix_[6]*center_[1] +
624 modelview_matrix_[10]*center_[2] +
625 modelview_matrix_[14] +
634QGLViewerWidget::set_scene_pos(
const OpenMesh::Vec3f& _cog,
float _radius )
638 glFogf( GL_FOG_START, 1.5*_radius );
639 glFogf( GL_FOG_END, 3.0*_radius );
641 update_projection_matrix();
653 draw_mode_names_.push_back(_s);
655 QActionGroup *grp = draw_modes_group_;
656 QAction* act =
new QAction(tr(_s.c_str()),
this);
657 act->setCheckable(
true);
658 act->setData(n_draw_modes_);
661 popup_menu_->addAction(act);
662 addAction(act, _s.c_str());
667void QGLViewerWidget::addAction(QAction* act,
const char * name)
669 names_to_actions[name] = act;
670 Super::addAction(act);
672void QGLViewerWidget::removeAction(QAction* act)
674 ActionMap::iterator it = names_to_actions.begin(), e = names_to_actions.end();
675 ActionMap::iterator found = e;
677 if (it->second == act) {
683 names_to_actions.erase(found);
685 popup_menu_->removeAction(act);
686 draw_modes_group_->removeAction(act);
687 Super::removeAction(act);
690void QGLViewerWidget::removeAction(
const char* name)
692 QString namestr = QString(name);
693 ActionMap::iterator e = names_to_actions.end();
695 ActionMap::iterator found = names_to_actions.find(namestr);
697 removeAction(found->second);
701QAction* QGLViewerWidget::findAction(
const char* name)
703 QString namestr = QString(name);
704 ActionMap::iterator e = names_to_actions.end();
706 ActionMap::iterator found = names_to_actions.find(namestr);
708 return found->second;
719 QString cmp = _s.c_str();
720 QList<QAction*> actions_ = popup_menu_->actions();
721 QList<QAction*>::iterator it=actions_.begin(), e=actions_.end();
723 if ((*it)->text() == cmp) {
break; }
733 popup_menu_->removeAction(*it);
743QGLViewerWidget::slotDrawMode(QAction* _mode)
746 draw_mode_ = _mode->data().toInt();
758QGLViewerWidget::performance()
760 setCursor( Qt::WaitCursor );
765 glMatrixMode(GL_MODELVIEW);
770 unsigned int frames = 60;
771 const float angle = 360.0/(float)frames;
778 for (i=0, axis=
Vec3f(1,0,0); i<frames; ++i)
779 { rotate(axis, angle); paintGL(); swapBuffers(); }
782 qApp->processEvents();
785 for (i=0, axis=
Vec3f(0,1,0); i<frames; ++i)
786 { rotate(axis, angle); paintGL(); swapBuffers(); }
789 qApp->processEvents();
792 for (i=0, axis=
Vec3f(0,0,1); i<frames; ++i)
793 { rotate(axis, angle); paintGL(); swapBuffers(); }
802 fps = ( (3.0 * frames) / timer.
seconds() );
804 setCursor( PointingHandCursor );
811QGLViewerWidget::slotSnapshot(
void )
814 size_t w(width()), h(height());
815 GLenum buffer( GL_BACK );
819 image = QImage(w, h, QImage::Format_RGB32);
821 std::vector<GLubyte> fbuffer(3*w*h);
823 qApp->processEvents();
828 glReadBuffer( buffer );
829 glPixelStorei(GL_PACK_ALIGNMENT, 1);
830 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
832 glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, &fbuffer[0] );
834 unsigned int x,y,offset;
836 for (y=0; y<h; ++y) {
837 for (x=0; x<w; ++x) {
838 offset = 3*(y*w + x);
839 image.setPixel(x, h-y-1, qRgb(fbuffer[offset],
846 QString name =
"snapshot-";
850 QDateTime dt = QDateTime::currentDateTime();
851 s << dt.date().year()
852 << std::setw(2) << std::setfill(
'0') << dt.date().month()
853 << std::setw(2) << std::setfill(
'0') << dt.date().day()
854 << std::setw(2) << std::setfill(
'0') << dt.time().hour()
855 << std::setw(2) << std::setfill(
'0') << dt.time().minute()
856 << std::setw(2) << std::setfill(
'0') << dt.time().second();
857 name += QString(s.str().c_str());
860 name += QDateTime::currentDateTime().toString(
"yyMMddhhmmss" );
864 image.save( name,
"PNG");
866 catch( std::bad_alloc& )
868 qWarning(
"Mem Alloc Error");
void cont(void)
Continue measurement.
void stop(void)
Stop measurement.
double seconds(void) const
Returns measured time in seconds, if the timer is in state 'Stopped'.
void start(void)
Start measurement.
decltype(std::declval< S >() *std::declval< S >()) sqrnorm() const
compute squared euclidean norm
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM > >().norm())
auto norm() const -> decltype(std::sqrt(std::declval< VectorT< S, DIM > >().sqrnorm()))
compute euclidean norm
T angle(T _cos_angle, T _sin_angle)