src/qvgui/qvglcanvas.cpp

Go to the documentation of this file.
00001 /*
00002  *      Copyright (C) 2007, 2008. 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/qvglcanvas.h>
00032 
00033 #define GL_VIEW_ASPECT   1.333
00034 
00035 QVGLCanvas::QVGLCanvas(const QString &title, QWidget* parent):
00036         QGLWidget(parent), maxwide(2.0), cx(0.0), cy(0.0), cz(0.0),
00037         trackballQuat(QVQuaternion::trackball(0.0, 0.0, 0.0, 0.0)),
00038         zoom(45), pressedleft(FALSE), pressedright(FALSE)
00039         {
00040         resize(400,(int)(400/GL_VIEW_ASPECT));
00041         setWindowTitle(title);
00042         show();
00043         }
00044 
00045 QVGLCanvas::~QVGLCanvas ()
00046         {
00047         // FIXME: is it needed?: makeCurrent(); 
00048         }
00049 
00053 void QVGLCanvas::linkModelMatrix(QVWorker &worker, const QString &matrixPropertyName, const QString &objectName)
00054         {
00056         worker.linkProperty(matrixPropertyName, this, objectName + " matrix", QVWorker::AsynchronousLink);
00057 
00059         QObject::connect(&worker, SIGNAL(endIteration()), this, SLOT(updateGL()));
00060         }
00061 
00062 void QVGLCanvas::add(const QV3DModel &model, const QString &name)
00063         {
00064         addProperty<QV3DModel>(name, inputFlag | outputFlag, model, name + " 3d object model");
00065         addProperty<QVMatrix>(name + " matrix", inputFlag | outputFlag, QVMatrix::identity(4), name + " 3d location matrix");
00066         }
00067 
00068 void QVGLCanvas::initializeGL()
00069         {
00070         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00071 
00072         glDisable(GL_CULL_FACE);
00073         glEnable(GL_DEPTH_TEST);
00074         
00075         glEnable(GL_DITHER);
00076         glShadeModel(GL_SMOOTH);
00077         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
00078         glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
00079         
00080         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
00081         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
00082         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
00083 
00084         glEnable(GL_DEPTH_TEST);
00085         glEnable(GL_CULL_FACE);
00086         glEnable(GL_TEXTURE_2D);
00087 
00088         init();
00089         }
00090 
00091 void QVGLCanvas::drawModels()
00092         {
00093         readInputProperties();
00094 
00095         glScaled((GLdouble)1/maxwide,(GLdouble)1/maxwide,(GLdouble)1/maxwide);
00096 
00097         foreach(QString name, getPropertyListByType<QV3DModel>())
00098                 {
00099                 QV3DModel model = getPropertyValue<QV3DModel>(name);
00100                 QVMatrix matrix = getPropertyValue<QVMatrix>(name + " matrix");
00101 
00102                 //std::cout << "maxwide = " << maxwide << std::endl;
00103                 //std::cout << "Matrix = " << matrix << std::endl;
00104                 //std::cout << "Model: '" << qPrintable(name) << "'." << std::endl;
00105                 if (matrix.getCols() == 4 && matrix.getRows() == 4)
00106                         {
00107                         glPushMatrix();
00108 
00110                         GLfloat m[4][4];
00111                         QVMatrix M = pseudoInverse(matrix);
00112 
00113                         for (int i=0; i <4; i++)
00114                                 for (int j=0; j <4; j++)
00115                                         m[i][j] = matrix(i,j);
00116 
00117                         for (int i=0; i <3; i++)
00118                                 { m[3][i] = 0; m[i][3] = 0; }
00119 
00120                         glTranslated(-M(0,3), -M(1,3), -M(2,3));
00121 
00122                         glMultMatrixf(&m[0][0]);
00123                         
00124                         model.paint(*this);
00125                         glPopMatrix();
00126 
00127                         glFlush();
00128                         }
00129                 else
00130                         model.paint(*this);
00131                 }
00132         }
00133 
00134 void QVGLCanvas::paintGL()
00135         {
00136         glMatrixMode(GL_PROJECTION);
00137 
00138         glLoadIdentity();
00139         gluPerspective(zoom,(float)size().width()/(float)size().height(),1,100);
00140         glMatrixMode(GL_MODELVIEW);
00141 
00142         glLoadIdentity();
00143         
00144         glTranslatef(0,0,-4); 
00145         glScaled((GLdouble)1/maxwide,(GLdouble)1/maxwide,(GLdouble)1/maxwide);
00146 
00147 
00148         GLfloat m[4][4];
00149         QVMatrix M(trackballQuat);
00150 
00151         for (int i=0; i <4; i++)
00152                 for (int j=0; j <4; j++)
00153                         m[i][j] = M(i,j);
00154 
00155         glMultMatrixf(&m[0][0]);
00156         
00157         glRotatef(270,1,0,0); 
00158         
00159         glTranslatef(-cx,-cy,-cz); 
00160 
00161         glClearColor(.5, .5, .75, 1.0);
00162         glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
00163 
00164         drawModels();
00165 
00166         display();
00167         }
00168 
00169 void QVGLCanvas::resizeGL( int w, int h )
00170         {
00171         glViewport(0,0,w,h); 
00172         reshape(w,h);
00173 
00174         drawModels();
00175         }
00176 
00180 
00181 void QVGLCanvas::mousePressEvent(QMouseEvent *event)
00182 {
00183     beginx = event->x();
00184     beginy = event->y();
00185     if(event->button() == Qt::LeftButton) {
00186         pressedleft = TRUE;
00187     } else if(event->button() == Qt::RightButton) {
00188         pressedright = TRUE;
00189     }
00190 }
00191 
00192 void QVGLCanvas::mouseReleaseEvent(QMouseEvent *event)
00193 {
00194     if(event->button() == Qt::LeftButton) {
00195         pressedleft = FALSE;
00196     } else if(event->button() == Qt::RightButton) {
00197         pressedright = FALSE;
00198     }
00199 }
00200 
00201 void QVGLCanvas::mouseMoveEvent(QMouseEvent *event)
00202 {
00203     int x,y;
00204 
00205     x = (int) event->x();
00206     y = (int) event->y();
00207 
00208     if (pressedleft) {
00209         QVQuaternion spinQuat = QVQuaternion::trackball(
00210                         (2.0*beginx - size().width())   / size().width(),
00211                         (size().height() - 2.0*beginy)  / size().height(),
00212                         (2.0*x - size().width())        / size().width(),
00213                         (size().height() - 2.0*y)       / size().height());
00214 
00215         trackballQuat = spinQuat * trackballQuat;
00216         updateGL();
00217     }
00218 
00219     if (pressedright) {
00220         /* zooming drag */
00221         //printf("MouseMove right button\n");
00222         zoom += ((y - beginy) / size().height()) * 40;
00223         if (zoom < 5) zoom = 5;
00224         if (zoom > 120) zoom = 120;
00225         /* zoom has changed, redraw  */
00226         updateGL();
00227     }
00228     beginx = x;
00229     beginy = y;
00230 }
00231 
00232 void QVGLCanvas::wheelEvent(QWheelEvent *event)
00233 {
00234     /* zooming wheel */
00235     zoom -= event->delta()/32;
00236     if (zoom < 5) zoom = 5;
00237     if (zoom > 120) zoom = 120;
00238     /* zoom has changed, redraw  */
00239     updateGL();
00240 }
00241 
00242 
00243 
00244 void QVGLCanvas::keyPressEvent(QKeyEvent *event)
00245 {
00246     //printf("KeyPress\n");
00247     switch(event->key()) {
00248       case Qt::Key_Left:
00249         cx -= maxwide/20;
00250         break;
00251       case Qt::Key_Right:
00252         cx += maxwide/20;
00253         break;
00254       case Qt::Key_Up:
00255         cy += maxwide/20;
00256         break;
00257       case Qt::Key_Down:
00258         cy -= maxwide/20;
00259         break;
00260       case Qt::Key_PageUp:
00261         cz += maxwide/20;
00262         break;
00263       case Qt::Key_PageDown:
00264         cz -= maxwide/20;
00265         break;
00266     }
00267     /* Ha cambiado el centro, redibujar: */
00268     updateGL();
00269 }
00270 
00271 void QVGLCanvas::closeEvent(QCloseEvent * event)
00272 {
00273         Q_UNUSED(event);
00274     emit closed();
00275 }
00276 
00278 
00279 int nearest_gl_texture_size(int v)
00280         {
00281         int n = 0, last = 0;
00282         for (int s = 0; s < 32; ++s)
00283                 {
00284                 if (((v>>s) & 1) == 1)
00285                         {
00286                         n++;
00287                         last = s;
00288                         }
00289                 }
00290 
00291         if (n > 1)
00292                 return 1 << (last+1);
00293         return 1 << last;
00294         }
00295 
00296 GLuint QVGLCanvas::bindTexture(const QVImage<uChar,3> &image, GLenum target)
00297         {
00298         const uInt cols = image.getCols(), rows = image.getRows(), step = image.getStep();
00299         bool clean = false;
00300 
00301         // Scale the pixmap if needed. GL textures needs to have the
00302         // dimensions 2^n+2(border) x 2^m+2(border).
00303         int textureImage_w = nearest_gl_texture_size(cols);
00304         int textureImage_h = nearest_gl_texture_size(rows);
00305 
00306         QVImage<uChar,3> textureImage(textureImage_w, textureImage_h);
00307         Resize(image, textureImage);
00308 
00309         GLuint textureImage_id;
00310         glGenTextures(1, &textureImage_id);
00311         glBindTexture(target, textureImage_id);
00312         glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00313         glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
00314         glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
00315         glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00316         glTexImage2D(target, 0, GL_RGB, textureImage_w, textureImage_h, 0, GL_BGR, GL_UNSIGNED_BYTE, textureImage.getReadData());
00317 
00318         return textureImage_id;
00319         }