00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #include <QMouseEvent>
00026
00027
00028 #include <qvdefines.h>
00029 #include <qvmatrixalgebra.h>
00030
00031 #include "qv3dcanvas.h"
00032 #include <QTimer>
00033 #define GL_VIEW_ASPECT 1.333
00034
00035 #ifndef DOXYGEN_IGNORE_THIS
00036 QV3DCanvas::QV3DCanvas( const QString &title, const double zoom, bool dr_center, const QColor &backgroundColor, QWidget* parent): QGLWidget(parent),
00037 trackballQuat(QVQuaternion::trackball(0.0, 0.0, 0.0, 0.0)),
00038 cx(0), cy(0), cz(0), ambientLightR(1.0), ambientLightG(1.0), ambientLightB(1.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
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
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
00102 glMatrixMode(GL_PROJECTION);
00103 glLoadIdentity();
00104
00105
00106 gluPerspective(fov, (float)size().width()/(float)size().height(), 0.25, 100*zoom);
00107
00108
00109 glMatrixMode(GL_MODELVIEW);
00110 glLoadIdentity();
00111
00112
00113 qglClearColor(backgroundColor);
00114
00115
00116 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
00117
00118
00119 glEnable(GL_LIGHTING);
00120
00121
00122 const GLfloat ambientLight[4] = {ambientLightR, ambientLightG, ambientLightB, 1.0 };
00123 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);
00124
00125 const double _low = 0.0, _high = 1.0;
00126
00127
00128 foreach(QString name, getPropertyList())
00129 if (getPropertyFlags(name) & inputFlag)
00130 {
00131
00132 if (isType< QVImage<uChar,1> >(name)) {
00133 QVImage<uChar, 1> imageAux = getPropertyValue<QVImage<uChar,1> >(name);
00134 drawQVImage(&imageAux);
00135 }
00136
00137 else if (isType< QVImage<uChar,3> >(name)) {
00138 QVImage<uChar,3> imageAux = getPropertyValue<QVImage<uChar,3> >(name);
00139 drawQVImage(&imageAux);
00140 }
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 }
00186
00187 glTranslatef(0,0,-8*zoom);
00188
00189 const QVMatrix R = (trackballQuat.toRotationMatrix() | QVVector(3,0.0)) & (QVVector(3,0.0) << 1);
00190
00191 glMultMatrixd(R.getReadData());
00192
00193 glTranslatef(cx,cy,cz);
00194
00195 display();
00196
00197 viewer();
00198
00199 if(dr_center)
00200 draw_center_of_rotation();
00201
00202
00203 glFlush();
00204 }
00205
00206 void QV3DCanvas::resizeGL( int w, int h )
00207 {
00208 glViewport(0,0,w,h);
00209 reshape(w,h);
00210
00211 glScaled((GLdouble)0.5,(GLdouble)0.5,(GLdouble)0.5);
00212
00213 viewer();
00214
00215 glFlush();
00216 }
00217
00221
00222 void QV3DCanvas::mousePressEvent(QMouseEvent *event)
00223 {
00224 beginx = event->x();
00225 beginy = event->y();
00226 if(event->button() == Qt::LeftButton) {
00227 pressedleft = TRUE;
00228 } else if(event->button() == Qt::RightButton) {
00229 pressedright = TRUE;
00230 }
00231 }
00232
00233 void QV3DCanvas::mouseReleaseEvent(QMouseEvent *event)
00234 {
00235 if(event->button() == Qt::LeftButton) {
00236 pressedleft = FALSE;
00237 } else if(event->button() == Qt::RightButton) {
00238 pressedright = FALSE;
00239 }
00240 }
00241
00242 void QV3DCanvas::mouseMoveEvent(QMouseEvent *event)
00243 {
00244 int x,y;
00245
00246 x = (int) event->x();
00247 y = (int) event->y();
00248
00249 if (pressedleft) {
00250 QVQuaternion spinQuat = QVQuaternion::trackball(
00251 (2.0*beginx - size().width()) / size().width(),
00252 (size().height() - 2.0*beginy) / size().height(),
00253 (2.0*x - size().width()) / size().width(),
00254 (size().height() - 2.0*y) / size().height());
00255
00256 trackballQuat = spinQuat * trackballQuat;
00257 updateGL();
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 beginx = x;
00269 beginy = y;
00270 }
00271
00272 void QV3DCanvas::wheelEvent(QWheelEvent *event)
00273 {
00274 zoom *= pow(0.9995,event->delta());
00275 updateGL();
00276 }
00277
00278 void QV3DCanvas::keyPressEvent(QKeyEvent *event)
00279 {
00280
00281 switch(event->key()) {
00282 case Qt::Key_Left:
00283 cx -= 0.1;
00284 break;
00285 case Qt::Key_Right:
00286 cx += 0.1;
00287 break;
00288 case Qt::Key_Up:
00289 cy += 0.1;
00290 break;
00291 case Qt::Key_Down:
00292 cy -= 0.1;
00293 break;
00294 case Qt::Key_PageUp:
00295 cz += 0.1;
00296 break;
00297 case Qt::Key_PageDown:
00298 cz -= 0.1;
00299 break;
00300 case 'C':
00301 dr_center = not dr_center;
00302 break;
00303
00304
00305
00306 }
00307
00308 updateGL();
00309 }
00310
00311 void QV3DCanvas::closeEvent(QCloseEvent * event)
00312 {
00313 Q_UNUSED(event);
00314 emit closed();
00315 }
00316
00318 #include <iostream>
00319 void QV3DCanvas::viewer()
00320 {
00321 qDebug() << "QVImageCanvas::viewer()";
00322 readInputProperties();
00323
00324
00325 foreach(QString name, getPropertyList())
00326 if (getPropertyFlags(name) & inputFlag)
00327 {
00328
00329 if (isType< QV3DPolylineF >(name))
00330 draw( getPropertyValue< QV3DPolylineF >(name),
00331 getPropertyValue<QColor>("Color for " + name),
00332 getPropertyValue<double>("Size for " + name));
00333
00334 else if (isType< QList<QV3DPointF> >(name))
00335 draw( getPropertyValue< QList<QV3DPointF> >(name),
00336 getPropertyValue<QColor>("Color for " + name),
00337 getPropertyValue<double>("Size for " + name));
00338
00339 else if (isType< QList<QV3DPolylineF> >(name))
00340 foreach(QV3DPolylineF polyline, getPropertyValue< QList<QV3DPolylineF> >(name))
00341 draw( polyline,
00342 getPropertyValue<QColor>("Color for " + name));
00343 }
00344
00345 foreach(QV3DModel *model, models)
00346 model->updatePaint(*this);
00347
00348 qDebug() << "QVImageCanvas::viewer() -> return";
00349 }
00350
00351 void QV3DCanvas::draw(const QV3DPolylineF &qv3DPolyline, const QColor color, const double size)
00352 {
00353 glPointSize(size);
00354 glBegin(GL_LINES);
00355 qglColor(color);
00356 for (int i = 1; i < qv3DPolyline.size(); i++)
00357 {
00358 glVertex3f(qv3DPolyline[i].x(), qv3DPolyline[i].y(), qv3DPolyline[i].z());
00359 glVertex3f(qv3DPolyline[i-1].x(), qv3DPolyline[i-1].y(), qv3DPolyline[i-1].z());
00360 }
00361 glEnd();
00362 }
00363
00364 #include <GL/glu.h>
00365 void QV3DCanvas::draw(const QList<QV3DPointF> &qv3DPointList, const QColor color, const double size)
00366 {
00367 foreach(QV3DPointF point, qv3DPointList)
00368 QV3DEllipsoid(color, size, size, size, point.x(), point.y(), point.z(), 10, 10).updatePaint(*this);
00369 }
00370
00371 bool QV3DCanvas::linkUnspecifiedInputProperty(QVPropertyContainer *sourceContainer, QString sourcePropName, LinkType linkType)
00372 {
00373 if (linkType == SynchronousLink)
00374 {
00375 std::cerr << "ERROR: QVImageCanvas::linkUnspecifiedInputProperty():"
00376 << " the linkType must be AsynchronousLink, the link will not be done"
00377 << std::endl;
00378 return false;
00379 }
00380
00381 QVProcessingBlock* block;
00382 if((block = dynamic_cast<QVProcessingBlock*>(sourceContainer)) != NULL)
00383 {
00384 std::cout << "QV3DCanvas: Adding property '" << qPrintable(sourcePropName) << "'" << std::endl;
00385 addPropertyFromQVariant(sourcePropName, inputFlag, block->getPropertyQVariantValue(sourcePropName), block->getPropertyInfo(sourcePropName));
00386 if ( block->isType< QV3DPolylineF >(sourcePropName) ||
00387 block->isType< QList<QV3DPointF> >(sourcePropName) ||
00388 block->isType< QList<QV3DPolylineF> >(sourcePropName) )
00389 {
00390 addProperty<QColor>("Color for " + sourcePropName, inputFlag, getNextColor(), QString("Color for object ") + sourcePropName);
00391 addProperty<double>("Size for " + sourcePropName, inputFlag, 1, QString("Size for object ") + sourcePropName);
00392 std::cout << "QV3DCanvas: Added property 'Color for " << qPrintable(sourcePropName) << "'" << std::endl;
00393 std::cout << "QV3DCanvas: Added property 'Size for " << qPrintable(sourcePropName) << "'" << std::endl;
00394 }
00395 bool result = block->linkProperty(sourcePropName, this, sourcePropName ,QVProcessingBlock::AsynchronousLink);
00396
00397 return result;
00398 }
00399 else
00400 {
00401 std::cerr << "ERROR: QVImageCanvas::linkUnspecifiedInputProperty(): the sourceContainer container must be a QVProcessingBlock, the link will not be done" << std::endl;
00402 return false;
00403 }
00404 }
00405
00406 void QV3DCanvas::drawQVImage(QVGenericImage *image)
00407 {
00408
00409 QVGenericImage *imagecopy=NULL;
00410 if(image->isCompatibleWith("QVImage<uChar,1>")) {
00411 imagecopy = new QVImage<uChar,1>;
00412 *(dynamic_cast<QVImage<uChar,1>*>(imagecopy)) = *(dynamic_cast<QVImage<uChar,1>*>(image));
00413 }
00414 else if(image->isCompatibleWith("QVImage<uChar,3>")) {
00415 imagecopy = new QVImage<uChar,3>;
00416 *(dynamic_cast<QVImage<uChar,3>*>(imagecopy)) = *(dynamic_cast<QVImage<uChar,3>*>(image));
00417 }
00418 else {
00419
00420 qFatal("Type of QVGenericImage still not supported in drawQVImage");
00421 }
00422
00424 const int cols = image->getCols(),
00425 rows = image->getRows();
00426
00427 setMinimumSize(cols,rows);
00428 setMaximumSize(cols,rows);
00429 resize(cols,rows);
00430
00431
00432
00433 glPushAttrib(GL_ALL_ATTRIB_BITS);
00434 glPushClientAttrib(GL_ALL_ATTRIB_BITS);
00435 glMatrixMode(GL_PROJECTION);
00436 glPushMatrix();
00437 glMatrixMode(GL_MODELVIEW);
00438 glPushMatrix();
00439
00440
00441
00442 glViewport(0,0,width(),height());
00443 glMatrixMode(GL_PROJECTION);
00444 glLoadIdentity();
00445
00446 glOrtho(0, cols, rows,0,-1,1);
00447 glMatrixMode(GL_MODELVIEW);
00448 glLoadIdentity();
00449
00450
00451 const QRect final_rect = QRect(imagecopy->getAnchor()+imagecopy->getROI().topLeft(),
00452 QSize(imagecopy->getROI().width(),imagecopy->getROI().height()));
00453
00454
00455
00456 const double zoom = 1.0;
00457
00458
00459 glRasterPos2f(0.0 , 0.0);
00460 glBitmap(0, 0, 0.0, 0.0, 0.0, 0.0, NULL);
00461 glPixelZoom(1.0,-1.0);
00462
00463
00464
00465 int img_step = imagecopy->getStep();
00466
00467
00468
00469
00470
00471
00472
00473
00474 if(image->isCompatibleWith("QVImage<uChar,1>"))
00475 {
00476 glPixelStorei(GL_UNPACK_ROW_LENGTH, img_step);
00477 glDrawPixels(cols, rows, GL_LUMINANCE, GL_UNSIGNED_BYTE, static_cast<QVImage<uchar,1> *>(imagecopy)->getReadData());
00478 }
00479 else if(image->isCompatibleWith("QVImage<uChar,3>"))
00480 {
00481 glPixelStorei(GL_UNPACK_ROW_LENGTH, img_step/3);
00482 glDrawPixels(cols, rows, GL_RGB, GL_UNSIGNED_BYTE, static_cast<QVImage<uchar,3> *>(imagecopy)->getReadData());
00483 }
00484 else
00485 qFatal("Type of QVGenericImage still not supported in drawQVImage");
00486
00487
00488
00489 glPopClientAttrib();
00490 glPopAttrib();
00491 glMatrixMode(GL_MODELVIEW);
00492 glPopMatrix();
00493 glMatrixMode(GL_PROJECTION);
00494 glPopMatrix();
00495 }
00496
00497 void QV3DEllipsoid::paint(QV3DCanvas &glWidget)
00498 {
00499 glWidget.qglColor(color);
00500
00501 for(int i = 0; i <= lats; i++)
00502 {
00503 double lat0 = M_PI * (-0.5 + (double) (i - 1) / lats);
00504 double z0 = sin(lat0);
00505 double zr0 = cos(lat0);
00506
00507 double lat1 = M_PI * (-0.5 + (double) i / lats);
00508 double z1 = sin(lat1);
00509 double zr1 = cos(lat1);
00510
00511 glBegin(GL_QUAD_STRIP);
00512 for(int j = 0; j <= longs; j++)
00513 {
00514 double lng = 2 * M_PI * (double) (j - 1) / longs;
00515 double x = cos(lng);
00516 double y = sin(lng);
00517
00518 glNormal3f(rx * x * zr0 + cx, ry * y * zr0 + cy, rz * z0 + cz);
00519 glVertex3f(rx * x * zr0 + cx, ry * y * zr0 + cy, rz * z0 + cz);
00520 glNormal3f(rx * x * zr1 + cx, ry * y * zr1 + cy, rz * z1 + cz);
00521 glVertex3f(rx * x * zr1 + cx, ry * y * zr1 + cy, rz * z1 + cz);
00522 }
00523 glEnd();
00524 }
00525 };
00526
00527
00528 #endif
00529