52 # pragma warning(disable: 4267 4311 4305)
66 #include <QApplication>
71 #include <QMouseEvent>
73 #include <OpenMesh/Apps/QtViewer/QGLViewerWidget.hh>
77 # define M_PI 3.1415926535897932
80 const double TRACKBALL_RADIUS = 0.6;
89 std::string QGLViewerWidget::nomode_ =
"";
93 QGLViewerWidget::QGLViewerWidget( QWidget* _parent )
94 : QGLWidget( _parent )
102 QGLViewerWidget( QGLFormat& _fmt, QWidget* _parent )
103 : QGLWidget( _fmt, _parent )
112 QGLViewerWidget::init(
void)
115 setAttribute(Qt::WA_NoSystemBackground,
true);
116 setFocusPolicy(Qt::StrongFocus);
117 setAcceptDrops(
true );
118 setCursor(PointingHandCursor);
123 popup_menu_ =
new QMenu(
this);
124 draw_modes_group_ =
new QActionGroup(
this);
126 connect( draw_modes_group_, SIGNAL(triggered(QAction*)),
127 this, SLOT(slotDrawMode(QAction*)));
135 a->setShortcut(QKeySequence(Key_W));
138 a->setShortcut(QKeySequence(Key_S));
147 QGLViewerWidget::~QGLViewerWidget()
155 QGLViewerWidget::setDefaultMaterial(
void)
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};
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);
172 QGLViewerWidget::setDefaultLight(
void)
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};
182 glLightfv(GL_LIGHT0,GL_POSITION, pos1);
183 glLightfv(GL_LIGHT0,GL_DIFFUSE, col1);
184 glLightfv(GL_LIGHT0,GL_SPECULAR, col1);
187 glLightfv(GL_LIGHT1,GL_POSITION, pos2);
188 glLightfv(GL_LIGHT1,GL_DIFFUSE, col2);
189 glLightfv(GL_LIGHT1,GL_SPECULAR, col2);
192 glLightfv(GL_LIGHT2,GL_POSITION, pos3);
193 glLightfv(GL_LIGHT2,GL_DIFFUSE, col3);
194 glLightfv(GL_LIGHT2,GL_SPECULAR, col3);
202 QGLViewerWidget::initializeGL()
205 glClearColor(0.0, 0.0, 0.0, 0.0);
206 glDisable( GL_DITHER );
207 glEnable( GL_DEPTH_TEST );
210 setDefaultMaterial();
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);
226 glMatrixMode(GL_MODELVIEW);
228 glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix_);
229 set_scene_pos(
Vec3f(0.0, 0.0, 0.0), 1.0);
237 QGLViewerWidget::resizeGL(
int _w,
int _h )
239 update_projection_matrix();
240 glViewport(0, 0, _w, _h);
249 QGLViewerWidget::paintGL()
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_ );
259 assert(draw_mode_ <= n_draw_modes_);
260 draw_scene(draw_mode_names_[draw_mode_-1]);
269 QGLViewerWidget::draw_scene(
const std::string& _draw_mode)
271 if (_draw_mode ==
"Wireframe")
273 glDisable(GL_LIGHTING);
277 else if (_draw_mode ==
"Solid Flat")
279 glEnable(GL_LIGHTING);
280 glShadeModel(GL_FLAT);
281 glutSolidTeapot(0.5);
284 else if (_draw_mode ==
"Solid Smooth")
286 glEnable(GL_LIGHTING);
287 glShadeModel(GL_SMOOTH);
288 glutSolidTeapot(0.5);
297 QGLViewerWidget::mousePressEvent( QMouseEvent* _event )
300 if (_event->button() == RightButton && _event->buttons()== RightButton )
302 popup_menu_->exec(QCursor::pos());
307 last_point_ok_ = map_to_sphere( last_point_2D_=_event->pos(),
317 QGLViewerWidget::mouseMoveEvent( QMouseEvent* _event )
319 QPoint newPoint2D = _event->pos();
327 bool newPoint_hitSphere = map_to_sphere( newPoint2D, newPoint3D );
329 float dx = newPoint2D.x() - last_point_2D_.x();
330 float dy = newPoint2D.y() - last_point_2D_.y();
342 if ( (_event->buttons() == (LeftButton+MidButton)) ||
343 (_event->buttons() == LeftButton && _event->modifiers() == ControlModifier))
345 float value_y = radius_ * dy * 3.0 / h;
346 translate(
Vec3f(0.0, 0.0, value_y));
351 else if ( (_event->buttons() == MidButton) ||
352 (_event->buttons() == LeftButton && _event->modifiers() == AltModifier) )
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]);
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;
368 translate(
Vec3f( 2.0*dx/w*right/near_plane*z,
369 -2.0*dy/h*top/near_plane*z,
376 else if (_event->buttons() == LeftButton) {
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);
387 Vec3f d = last_point_3D_ - newPoint3D;
388 float t = 0.5 * d.norm() / TRACKBALL_RADIUS;
393 float phi = 2.0 * asin(t);
394 float angle = phi * 180.0 / M_PI;
403 last_point_2D_ = newPoint2D;
404 last_point_3D_ = newPoint3D;
405 last_point_ok_ = newPoint_hitSphere;
416 QGLViewerWidget::mouseReleaseEvent( QMouseEvent* )
418 last_point_ok_ =
false;
425 void QGLViewerWidget::wheelEvent(QWheelEvent* _event)
429 float d = -(float)_event->delta() / 120.0 * 0.2 * radius_;
430 translate(
Vec3f(0.0, 0.0, d));
439 void QGLViewerWidget::keyPressEvent( QKeyEvent* _event)
441 switch( _event->key() )
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";
459 if ( glIsEnabled( GL_CULL_FACE ) )
461 glDisable( GL_CULL_FACE );
462 std::cout <<
"Back face culling: disabled\n";
466 glEnable( GL_CULL_FACE );
467 std::cout <<
"Back face culling: enabled\n";
473 if ( glIsEnabled( GL_FOG ) )
476 std::cout <<
"Fog: disabled\n";
481 std::cout <<
"Fog: enabled\n";
487 std::cout <<
"Scene radius: " << radius_ << std::endl;
488 std::cout <<
"Scene center: " << center_ << std::endl;
492 if (_event->modifiers() & ShiftModifier)
494 double fps = performance();
496 << std::setiosflags (std::ios_base::fixed)
519 glTranslated( _trans[0], _trans[1], _trans[2] );
520 glMultMatrixd( modelview_matrix_ );
521 glGetDoublev( GL_MODELVIEW_MATRIX, modelview_matrix_);
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] );
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_);
561 QGLViewerWidget::map_to_sphere(
const QPoint& _v2D,
OpenMesh::Vec3f& _v3D )
565 double x = (2.0*_v2D.x() - width())/width();
566 double y = -(2.0*_v2D.y() - height())/height();
569 double x2y2 = xval*xval + yval*yval;
571 const double rsqr = TRACKBALL_RADIUS*TRACKBALL_RADIUS;
574 if (x2y2 < 0.5*rsqr) {
575 _v3D[2] = sqrt(rsqr - x2y2);
577 _v3D[2] = 0.5*rsqr/sqrt(x2y2);
588 QGLViewerWidget::update_projection_matrix()
591 glMatrixMode( GL_PROJECTION );
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 );
604 QGLViewerWidget::view_all()
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] +
626 QGLViewerWidget::set_scene_pos(
const OpenMesh::Vec3f& _cog,
float _radius )
630 glFogf( GL_FOG_START, 1.5*_radius );
631 glFogf( GL_FOG_END, 3.0*_radius );
633 update_projection_matrix();
645 draw_mode_names_.push_back(_s);
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_);
653 popup_menu_->addAction(act);
654 addAction(act, _s.c_str());
659 void QGLViewerWidget::addAction(QAction* act,
const char * name)
661 names_to_actions[name] = act;
662 Super::addAction(act);
664 void QGLViewerWidget::removeAction(QAction* act)
666 ActionMap::iterator it = names_to_actions.begin(), e = names_to_actions.end();
667 ActionMap::iterator found = e;
669 if (it->second == act) {
675 names_to_actions.erase(found);
677 popup_menu_->removeAction(act);
678 draw_modes_group_->removeAction(act);
679 Super::removeAction(act);
682 void QGLViewerWidget::removeAction(
const char* name)
684 QString namestr = QString(name);
685 ActionMap::iterator e = names_to_actions.end();
687 ActionMap::iterator found = names_to_actions.find(namestr);
689 removeAction(found->second);
693 QAction* QGLViewerWidget::findAction(
const char* name)
695 QString namestr = QString(name);
696 ActionMap::iterator e = names_to_actions.end();
698 ActionMap::iterator found = names_to_actions.find(namestr);
700 return found->second;
711 QString cmp = _s.c_str();
712 QList<QAction*> actions_ = popup_menu_->actions();
713 QList<QAction*>::iterator it=actions_.begin(), e=actions_.end();
715 if ((*it)->text() == cmp) {
break; }
725 popup_menu_->removeAction(*it);
735 QGLViewerWidget::slotDrawMode(QAction* _mode)
738 draw_mode_ = _mode->data().toInt();
750 QGLViewerWidget::performance()
752 setCursor( Qt::WaitCursor );
757 glMatrixMode(GL_MODELVIEW);
762 unsigned int frames = 60;
763 const float angle = 360.0/(float)frames;
770 for (i=0, axis=
Vec3f(1,0,0); i<frames; ++i)
771 { rotate(axis, angle); paintGL(); swapBuffers(); }
774 qApp->processEvents();
777 for (i=0, axis=
Vec3f(0,1,0); i<frames; ++i)
778 { rotate(axis, angle); paintGL(); swapBuffers(); }
781 qApp->processEvents();
784 for (i=0, axis=
Vec3f(0,0,1); i<frames; ++i)
785 { rotate(axis, angle); paintGL(); swapBuffers(); }
794 fps = ( (3.0 * frames) / timer.
seconds() );
796 setCursor( PointingHandCursor );
803 QGLViewerWidget::slotSnapshot(
void )
806 size_t w(width()), h(height());
807 GLenum buffer( GL_BACK );
811 image = QImage(w, h, QImage::Format_RGB32);
813 std::vector<GLubyte> fbuffer(3*w*h);
815 qApp->processEvents();
820 glReadBuffer( buffer );
821 glPixelStorei(GL_PACK_ALIGNMENT, 1);
822 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
824 glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, &fbuffer[0] );
826 unsigned int x,y,offset;
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],
838 QString name =
"snapshot-";
839 #if defined(_MSC_VER)
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());
852 name += QDateTime::currentDateTime().toString(
"yyMMddhhmmss" );
856 image.save( name,
"PNG");
858 catch( std::bad_alloc& )
860 qWarning(
"Mem Alloc Error");
void stop(void)
Stop measurement.
void del_draw_mode(const std::string &_s)
delete draw mode from popup menu
void start(void)
Start measurement.
QAction * add_draw_mode(const std::string &_s)
add draw mode to popup menu, and return the QAction created
double seconds(void) const
Returns measured time in seconds, if the timer is in state 'Stopped'.
void cont(void)
Continue measurement.
T angle(T _cos_angle, T _sin_angle)