PARP Research Group University of Murcia, Spain


src/qvgui/qv3dcanvas.cpp

Go to the documentation of this file.
00001 /*
00002  *      Copyright (C) 2007, 2008, 2009. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00024 
00025 #include <QMouseEvent>
00026 
00027 #include <qvipp.h>
00028 #include <qvdefines.h>
00029 #include <qvmatrixalgebra.h>
00030 
00031 #include <qvgui/qv3dcanvas.h>
00032 #include <QTimer>
00033 #define GL_VIEW_ASPECT   1.333
00034 
00035 
00036 QV3DCanvas::QV3DCanvas( const QString &title, const double zoom,
00037                         bool dr_center, const QColor &backgroundColor, QWidget* parent): QGLWidget(parent),
00038                         trackballQuat(QVQuaternion::trackball(0.0, 0.0, 0.0, 0.0)), cx(0), cy(0), cz(0),
00039                         dr_center(dr_center), zoom(zoom), fov(45), pressedleft(FALSE), pressedright(FALSE), colorCursor(0), backgroundColor(backgroundColor)
00040         {
00041         setName(title);
00042 
00043         resize(400,(int)(400/GL_VIEW_ASPECT));
00044         setWindowTitle(title);
00045 
00046         QTimer *timer = new QTimer(this);
00047         connect(timer, SIGNAL(timeout()), this, SLOT(updateGL()));
00048         timer->start(1000/24);
00049 
00050         show();
00051         }
00052 
00053 QV3DCanvas::~QV3DCanvas ()
00054         {
00055         // FIXME: is it needed?: makeCurrent(); 
00056         }
00057 
00058 void QV3DCanvas::initializeGL()
00059         {
00060         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00061 
00062         glDisable(GL_CULL_FACE);
00063         glEnable(GL_DEPTH_TEST);
00064         
00065         glEnable(GL_DITHER);
00066         glShadeModel(GL_SMOOTH);
00067         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
00068         glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
00069         
00070         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
00071         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
00072         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
00073 
00074         glEnable(GL_DEPTH_TEST);
00075         glEnable(GL_CULL_FACE);
00076         glEnable(GL_TEXTURE_2D);
00077 
00078         init();
00079         }
00080 
00081 void QV3DCanvas::draw_center_of_rotation()
00082         {
00083         /* Yellow cross: (center of rotation). */
00084         glBegin(GL_LINES);
00085                 glColor3ub(255,255,0);
00086                 
00087                 glVertex3f(cx - 0.1,cy,cz);
00088                 glVertex3f(cx + 0.1,cy,cz);
00089                 
00090                 glVertex3f(cx,cy- 0.1,cz);
00091                 glVertex3f(cx,cy+ 0.1,cz);
00092                 
00093                 glVertex3f(cx,cy,cz- 0.1);
00094                 glVertex3f(cx,cy,cz+ 0.1);
00095         glEnd();
00096         }
00097 
00098 #define S       15
00099 void QV3DCanvas::paintGL()
00100         {
00101         glMatrixMode(GL_PROJECTION);
00102 
00103         glLoadIdentity();
00104         gluPerspective(fov,(float)size().width()/(float)size().height(),1,100*zoom);
00105         glMatrixMode(GL_MODELVIEW);
00106 
00107         qglClearColor(backgroundColor);
00108         glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
00109 
00110         glLoadIdentity();
00111         
00112         glTranslatef(0,0,-4*zoom); 
00113         glScaled((GLdouble)0.5/zoom,(GLdouble)0.5/zoom,(GLdouble)0.5/zoom);
00114 
00115         QVMatrix M(trackballQuat);
00116         GLfloat m[4][4];
00117 
00118         for (int i=0; i <4; i++)
00119                 for (int j=0; j <4; j++)
00120                         m[i][j] = M(i,j);
00121 
00122         glMultMatrixf(&m[0][0]);
00123         
00124         glRotatef(270,1,0,0); 
00125         
00126         glTranslatef(-cx,-cy,-cz); 
00127 
00128         if(dr_center)
00129                 draw_center_of_rotation();
00130 
00131         glScaled((GLdouble)0.5,(GLdouble)0.5,(GLdouble)0.5);
00132 
00133         viewer();
00134 
00135         display();
00136         }
00137 
00138 void QV3DCanvas::resizeGL( int w, int h )
00139         {
00140         glViewport(0,0,w,h); 
00141         reshape(w,h);
00142 
00143         glScaled((GLdouble)0.5,(GLdouble)0.5,(GLdouble)0.5);
00144 
00145         viewer();
00146         }
00147 
00151 
00152 void QV3DCanvas::mousePressEvent(QMouseEvent *event)
00153 {
00154     beginx = event->x();
00155     beginy = event->y();
00156     if(event->button() == Qt::LeftButton) {
00157         pressedleft = TRUE;
00158     } else if(event->button() == Qt::RightButton) {
00159         pressedright = TRUE;
00160     }
00161 }
00162 
00163 void QV3DCanvas::mouseReleaseEvent(QMouseEvent *event)
00164 {
00165     if(event->button() == Qt::LeftButton) {
00166         pressedleft = FALSE;
00167     } else if(event->button() == Qt::RightButton) {
00168         pressedright = FALSE;
00169     }
00170 }
00171 
00172 void QV3DCanvas::mouseMoveEvent(QMouseEvent *event)
00173 {
00174     int x,y;
00175 
00176     x = (int) event->x();
00177     y = (int) event->y();
00178 
00179     if (pressedleft) {
00180         QVQuaternion spinQuat = QVQuaternion::trackball(
00181                         (2.0*beginx - size().width())   / size().width(),
00182                         (size().height() - 2.0*beginy)  / size().height(),
00183                         (2.0*x - size().width())        / size().width(),
00184                         (size().height() - 2.0*y)       / size().height());
00185 
00186         trackballQuat = spinQuat * trackballQuat;
00187         updateGL();
00188     }
00189 /*
00190     if (pressedright) {
00191         //printf("MouseMove right button\n");
00192         zoom += ((y - beginy) / size().height()) * 100;
00193 
00194         //if (zoom < 5) zoom = 5;
00195         //if (zoom > 120) zoom = 120;
00196         updateGL();
00197     }*/
00198     beginx = x;
00199     beginy = y;
00200 }
00201 
00202 void QV3DCanvas::wheelEvent(QWheelEvent *event)
00203         {
00204         zoom *= pow(0.9995,event->delta());
00205         updateGL();
00206         }
00207 
00208 void QV3DCanvas::keyPressEvent(QKeyEvent *event)
00209 {
00210     //printf("KeyPress\n");
00211     switch(event->key()) {
00212       case Qt::Key_Left:
00213         cx -= 0.1; // maxwide/20;
00214         break;
00215       case Qt::Key_Right:
00216         cx += 0.1; // maxwide/20;
00217         break;
00218       case Qt::Key_Up:
00219         cy += 0.1; // maxwide/20;
00220         break;
00221       case Qt::Key_Down:
00222         cy -= 0.1; // maxwide/20;
00223         break;
00224       case Qt::Key_PageUp:
00225         cz += 0.1; // maxwide/20;
00226         break;
00227       case Qt::Key_PageDown:
00228         cz -= 0.1; // maxwide/20;
00229         break;
00230       case 'C':
00231         dr_center = not dr_center;
00232         break;
00233       //case 'B':
00234         //dr_box = not dr_box;
00235         //break;
00236     }
00237     /* Something changed; redraw: */
00238     updateGL();
00239 }
00240 
00241 void QV3DCanvas::closeEvent(QCloseEvent * event)
00242 {
00243         Q_UNUSED(event);
00244         emit closed();
00245 }
00246 
00248 #include <iostream>
00249 void QV3DCanvas::viewer()
00250         {
00251         qDebug() << "QVImageCanvas::viewer()";
00252         readInputProperties();
00253 
00254         // Draw other objects
00255         foreach(QString name, getPropertyList())
00256                 if (getPropertyFlags(name) & inputFlag)
00257                         {
00258                         // Draw QV3DPolylineF
00259                         if (isType< QV3DPolylineF >(name))
00260                                 draw(   getPropertyValue< QV3DPolylineF >(name),
00261                                         getPropertyValue<QColor>("Color for " + name),
00262                                         getPropertyValue<double>("Size for " + name));
00263                         // Draw QList<QV3DPointF>
00264                         else if (isType< QList<QV3DPointF> >(name))
00265                                 draw(   getPropertyValue< QList<QV3DPointF> >(name),
00266                                         getPropertyValue<QColor>("Color for " + name),
00267                                         getPropertyValue<double>("Size for " + name));
00268                         // Draw QList<QV3DPolylineF>
00269                         else if (isType< QList<QV3DPolylineF> >(name))
00270                                 foreach(QV3DPolylineF polyline, getPropertyValue< QList<QV3DPolylineF> >(name))
00271                                         draw(   polyline,
00272                                                 getPropertyValue<QColor>("Color for " + name));
00273                         }
00274 
00275         foreach(QV3DModel *model, models)
00276                 model->updatePaint(*this);
00277 
00278         glFlush();
00279         qDebug() << "QVImageCanvas::viewer() -> return";
00280         }
00281 
00282 void QV3DCanvas::draw(const QV3DPolylineF &qv3DPolyline, const QColor color, const double size)
00283         {
00284         glPointSize(size);
00285         glBegin(GL_LINES);
00286         qglColor(color);
00287         for (int i = 1; i < qv3DPolyline.size(); i++)
00288                 {
00289                 glVertex3f(qv3DPolyline[i].x(), qv3DPolyline[i].y(), qv3DPolyline[i].z());
00290                 glVertex3f(qv3DPolyline[i-1].x(), qv3DPolyline[i-1].y(), qv3DPolyline[i-1].z());
00291                 }
00292         glEnd();
00293         }
00294 
00295 #include <GL/glu.h>
00296 void QV3DCanvas::draw(const QList<QV3DPointF> &qv3DPointList, const QColor color, const double size)
00297         {
00298         glPointSize(size);
00299         glEnable(GL_POINT_SMOOTH);
00300         glBegin( GL_POINTS );
00301         qglColor(color);
00302         foreach(QV3DPointF point, qv3DPointList)
00303                 glVertex3f(point.x(), point.y(), point.z());
00304         glEnd();
00305 
00306         glBegin(GL_LINES);
00307         glColor3ub(color.red()/2, color.green()/2, color.blue()/2);
00308         foreach(QV3DPointF point, qv3DPointList)
00309                 {
00310                 glVertex3f(point.x(), point.y(), point.z());
00311                 glVertex3f(point.x(), point.y(), 0);
00312                 }
00313         glEnd();
00314 
00315         }
00316 
00317 bool QV3DCanvas::linkUnspecifiedInputProperty(QVPropertyContainer *sourceContainer, QString sourcePropName, LinkType linkType)
00318         {
00319         if (linkType == SynchronousLink)
00320                 {
00321                 std::cerr       << "ERROR: QVImageCanvas::linkUnspecifiedInputProperty():"
00322                                 << " the linkType must be AsynchronousLink, the link will not be done"
00323                                 << std::endl;
00324                 return false;
00325                 }
00326 
00327         QVWorker* worker;
00328         if((worker = dynamic_cast<QVWorker*>(sourceContainer)) != NULL)
00329                 {
00330                 if (    worker->isType< QV3DPolylineF >(sourcePropName)         ||
00331                         worker->isType< QList<QV3DPointF> >(sourcePropName)     ||
00332                         worker->isType< QList<QV3DPolylineF> >(sourcePropName)          )
00333                         {
00334                         addPropertyFromQVariant(sourcePropName, inputFlag, worker->getPropertyQVariantValue(sourcePropName), worker->getPropertyInfo(sourcePropName));
00335                         addProperty<QColor>("Color for " + sourcePropName, inputFlag, getNextColor(), QString("Color for object ") + sourcePropName);
00336                         addProperty<double>("Size for " + sourcePropName, inputFlag, 1, QString("Size for object ") + sourcePropName);
00337                         }
00338                 bool result = worker->linkProperty(sourcePropName, this, sourcePropName ,QVWorker::AsynchronousLink);
00339                 //QObject::connect(worker, SIGNAL(endIteration(uint, int)), this, SLOT(refreshImageArea()));
00340                 return result;
00341                 }
00342         else
00343                 {
00344                 std::cerr << "ERROR: QVImageCanvas::linkUnspecifiedInputProperty(): the sourceContainer container must be a QVWorker, the link will not be done" << std::endl;
00345                 return false;
00346                 }
00347 
00348         }



QVision framework. PARP research group, copyright 2007, 2008.