47 # pragma warning(disable: 4267 4311 4305) 57 #include <QApplication> 62 #include <QMouseEvent> 64 #include <OpenMesh/Apps/QtViewer/QGLViewerWidget.hh> 68 # define M_PI 3.1415926535897932 71 const double TRACKBALL_RADIUS = 0.6;
80 std::string QGLViewerWidget::nomode_ =
"";
84 QGLViewerWidget::QGLViewerWidget( QWidget* _parent )
85 : QGLWidget( _parent )
93 QGLViewerWidget( QGLFormat& _fmt, QWidget* _parent )
94 : QGLWidget( _fmt, _parent )
103 QGLViewerWidget::init(
void)
106 setAttribute(Qt::WA_NoSystemBackground,
true);
107 setFocusPolicy(Qt::StrongFocus);
108 setAcceptDrops(
true );
109 setCursor(PointingHandCursor);
114 popup_menu_ =
new QMenu(
this);
115 draw_modes_group_ =
new QActionGroup(
this);
117 connect( draw_modes_group_, SIGNAL(triggered(QAction*)),
118 this, SLOT(slotDrawMode(QAction*)));
126 a->setShortcut(QKeySequence(Key_W));
129 a->setShortcut(QKeySequence(Key_S));
138 QGLViewerWidget::~QGLViewerWidget()
146 QGLViewerWidget::setDefaultMaterial(
void)
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};
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);
163 QGLViewerWidget::setDefaultLight(
void)
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};
173 glLightfv(GL_LIGHT0,GL_POSITION, pos1);
174 glLightfv(GL_LIGHT0,GL_DIFFUSE, col1);
175 glLightfv(GL_LIGHT0,GL_SPECULAR, col1);
178 glLightfv(GL_LIGHT1,GL_POSITION, pos2);
179 glLightfv(GL_LIGHT1,GL_DIFFUSE, col2);
180 glLightfv(GL_LIGHT1,GL_SPECULAR, col2);
183 glLightfv(GL_LIGHT2,GL_POSITION, pos3);
184 glLightfv(GL_LIGHT2,GL_DIFFUSE, col3);
185 glLightfv(GL_LIGHT2,GL_SPECULAR, col3);
193 QGLViewerWidget::initializeGL()
196 glClearColor(0.0, 0.0, 0.0, 0.0);
197 glDisable( GL_DITHER );
198 glEnable( GL_DEPTH_TEST );
201 setDefaultMaterial();
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);
217 glMatrixMode(GL_MODELVIEW);
219 glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix_);
220 set_scene_pos(
Vec3f(0.0, 0.0, 0.0), 1.0);
228 QGLViewerWidget::resizeGL(
int _w,
int _h )
230 update_projection_matrix();
231 glViewport(0, 0, _w, _h);
240 QGLViewerWidget::paintGL()
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_ );
250 assert(draw_mode_ <= n_draw_modes_);
260 QGLViewerWidget::draw_scene(
const std::string& _draw_mode)
262 if (_draw_mode ==
"Wireframe")
264 glDisable(GL_LIGHTING);
268 else if (_draw_mode ==
"Solid Flat")
270 glEnable(GL_LIGHTING);
271 glShadeModel(GL_FLAT);
275 else if (_draw_mode ==
"Solid Smooth")
277 glEnable(GL_LIGHTING);
278 glShadeModel(GL_SMOOTH);
288 QGLViewerWidget::mousePressEvent( QMouseEvent* _event )
291 if (_event->button() == RightButton && _event->buttons()== RightButton )
293 popup_menu_->exec(QCursor::pos());
298 last_point_ok_ = map_to_sphere( last_point_2D_=_event->pos(),
308 QGLViewerWidget::mouseMoveEvent( QMouseEvent* _event )
310 QPoint newPoint2D = _event->pos();
318 bool newPoint_hitSphere = map_to_sphere( newPoint2D, newPoint3D );
320 float dx = newPoint2D.x() - last_point_2D_.x();
321 float dy = newPoint2D.y() - last_point_2D_.y();
333 if ( (_event->buttons() == (LeftButton+MidButton)) ||
334 (_event->buttons() == LeftButton && _event->modifiers() == ControlModifier))
336 float value_y = radius_ * dy * 3.0 / h;
342 else if ( (_event->buttons() == MidButton) ||
343 (_event->buttons() == LeftButton && _event->modifiers() == AltModifier) )
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]);
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;
360 -2.0*dy/h*top/near_plane*z,
367 else if (_event->buttons() == LeftButton) {
369 if (last_point_ok_) {
370 if ((newPoint_hitSphere = map_to_sphere(newPoint2D, newPoint3D))) {
371 Vec3f axis = last_point_3D_ % newPoint3D;
373 axis =
Vec3f(1, 0, 0);
378 Vec3f d = last_point_3D_ - newPoint3D;
379 float t = 0.5 * d.
norm() / TRACKBALL_RADIUS;
384 float phi = 2.0 * asin(t);
385 float angle = phi * 180.0 / M_PI;
394 last_point_2D_ = newPoint2D;
395 last_point_3D_ = newPoint3D;
396 last_point_ok_ = newPoint_hitSphere;
407 QGLViewerWidget::mouseReleaseEvent( QMouseEvent* )
409 last_point_ok_ =
false;
416 void QGLViewerWidget::wheelEvent(QWheelEvent* _event)
420 float d = -(float)_event->delta() / 120.0 * 0.2 * radius_;
430 void QGLViewerWidget::keyPressEvent( QKeyEvent* _event)
432 switch( _event->key() )
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";
450 if ( glIsEnabled( GL_CULL_FACE ) )
452 glDisable( GL_CULL_FACE );
453 std::cout <<
"Back face culling: disabled\n";
457 glEnable( GL_CULL_FACE );
458 std::cout <<
"Back face culling: enabled\n";
464 if ( glIsEnabled( GL_FOG ) )
467 std::cout <<
"Fog: disabled\n";
472 std::cout <<
"Fog: enabled\n";
478 std::cout <<
"Scene radius: " << radius_ << std::endl;
479 std::cout <<
"Scene center: " << center_ << std::endl;
483 if (_event->modifiers() & ShiftModifier)
485 double fps = performance();
487 << std::setiosflags (std::ios_base::fixed)
510 glTranslated( _trans[0], _trans[1], _trans[2] );
511 glMultMatrixd( modelview_matrix_ );
512 glGetDoublev( GL_MODELVIEW_MATRIX, modelview_matrix_);
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] );
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_);
552 QGLViewerWidget::map_to_sphere(
const QPoint& _v2D,
OpenMesh::Vec3f& _v3D )
556 double x = (2.0*_v2D.x() - width())/width();
557 double y = -(2.0*_v2D.y() - height())/height();
560 double x2y2 = xval*xval + yval*yval;
562 const double rsqr = TRACKBALL_RADIUS*TRACKBALL_RADIUS;
565 if (x2y2 < 0.5*rsqr) {
566 _v3D[2] = sqrt(rsqr - x2y2);
568 _v3D[2] = 0.5*rsqr/sqrt(x2y2);
579 QGLViewerWidget::update_projection_matrix()
582 glMatrixMode( GL_PROJECTION );
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_;
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 );
597 glGetDoublev( GL_PROJECTION_MATRIX, projection_matrix_);
598 glMatrixMode( GL_MODELVIEW );
606 QGLViewerWidget::view_all()
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] +
628 QGLViewerWidget::set_scene_pos(
const OpenMesh::Vec3f& _cog,
float _radius )
632 glFogf( GL_FOG_START, 1.5*_radius );
633 glFogf( GL_FOG_END, 3.0*_radius );
635 update_projection_matrix();
647 draw_mode_names_.push_back(_s);
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_);
655 popup_menu_->addAction(act);
656 addAction(act, _s.c_str());
661 void QGLViewerWidget::addAction(QAction* act,
const char * name)
663 names_to_actions[name] = act;
664 Super::addAction(act);
666 void QGLViewerWidget::removeAction(QAction* act)
668 ActionMap::iterator it = names_to_actions.begin(), e = names_to_actions.end();
669 ActionMap::iterator found = e;
671 if (it->second == act) {
677 names_to_actions.erase(found);
679 popup_menu_->removeAction(act);
680 draw_modes_group_->removeAction(act);
681 Super::removeAction(act);
684 void QGLViewerWidget::removeAction(
const char* name)
686 QString namestr = QString(name);
687 ActionMap::iterator e = names_to_actions.end();
689 ActionMap::iterator found = names_to_actions.find(namestr);
691 removeAction(found->second);
695 QAction* QGLViewerWidget::findAction(
const char* name)
697 QString namestr = QString(name);
698 ActionMap::iterator e = names_to_actions.end();
700 ActionMap::iterator found = names_to_actions.find(namestr);
702 return found->second;
713 QString cmp = _s.c_str();
714 QList<QAction*> actions_ = popup_menu_->actions();
715 QList<QAction*>::iterator it=actions_.begin(), e=actions_.end();
717 if ((*it)->text() == cmp) {
break; }
727 popup_menu_->removeAction(*it);
737 QGLViewerWidget::slotDrawMode(QAction* _mode)
740 draw_mode_ = _mode->data().toInt();
752 QGLViewerWidget::performance()
754 setCursor( Qt::WaitCursor );
759 glMatrixMode(GL_MODELVIEW);
764 unsigned int frames = 60;
765 const float angle = 360.0/(float)frames;
772 for (i=0, axis=
Vec3f(1,0,0); i<frames; ++i)
773 { rotate(axis, angle); paintGL(); swapBuffers(); }
776 qApp->processEvents();
779 for (i=0, axis=
Vec3f(0,1,0); i<frames; ++i)
780 { rotate(axis, angle); paintGL(); swapBuffers(); }
783 qApp->processEvents();
786 for (i=0, axis=
Vec3f(0,0,1); i<frames; ++i)
787 { rotate(axis, angle); paintGL(); swapBuffers(); }
796 fps = ( (3.0 * frames) / timer.
seconds() );
798 setCursor( PointingHandCursor );
805 QGLViewerWidget::slotSnapshot(
void )
808 size_t w(width()), h(height());
809 GLenum buffer( GL_BACK );
813 image = QImage(w, h, QImage::Format_RGB32);
815 std::vector<GLubyte> fbuffer(3*w*h);
817 qApp->processEvents();
822 glReadBuffer( buffer );
823 glPixelStorei(GL_PACK_ALIGNMENT, 1);
824 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
826 glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, &fbuffer[0] );
828 unsigned int x,y,offset;
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],
840 QString name =
"snapshot-";
841 #if defined(_MSC_VER) 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());
854 name += QDateTime::currentDateTime().toString(
"yyMMddhhmmss" );
858 image.save( name,
"PNG");
860 catch( std::bad_alloc& )
862 qWarning(
"Mem Alloc Error");
T angle(T _cos_angle, T _sin_angle)
double seconds(void) const
Returns measured time in seconds, if the timer is in state 'Stopped'.
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
decltype(std::declval< S >() *std::declval< S >()) sqrnorm() const
compute squared euclidean norm
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())