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
00034 #include <GL/glu.h>
00035
00036 #define GL_VIEW_ASPECT 1.333
00037
00038 #ifndef DOXYGEN_IGNORE_THIS
00039 QV3DCanvas::QV3DCanvas( const QString &title, const double zoom, bool dr_center, const QColor &backgroundColor, QWidget* parent): QGLWidget(parent),
00040 trackballQuat(QVQuaternion::trackball(0.0, 0.0, 0.0, 0.0)),
00041 cx(0), cy(0), cz(0), ambientLightR(1.0), ambientLightG(1.0), ambientLightB(1.0),
00042 dr_center(dr_center), zoom(zoom), fov(45), pressedleft(FALSE), pressedright(FALSE), colorCursor(0), backgroundColor(backgroundColor)
00043 {
00044 setName(title);
00045
00046 resize(400,(int)(400/GL_VIEW_ASPECT));
00047 setWindowTitle(title);
00048
00049 QTimer *timer = new QTimer(this);
00050 connect(timer, SIGNAL(timeout()), this, SLOT(updateGL()));
00051 timer->start(1000/24);
00052
00053 show();
00054 }
00055
00056 QV3DCanvas::~QV3DCanvas ()
00057 {
00058
00059 }
00060
00061 void QV3DCanvas::initializeGL()
00062 {
00063 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00064
00065 glDisable(GL_CULL_FACE);
00066 glEnable(GL_DEPTH_TEST);
00067
00068 glEnable(GL_DITHER);
00069 glShadeModel(GL_SMOOTH);
00070 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
00071 glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
00072
00073 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00074 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00075 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
00076
00077 glEnable(GL_DEPTH_TEST);
00078 glEnable(GL_CULL_FACE);
00079 glEnable(GL_TEXTURE_2D);
00080
00081 init();
00082 }
00083
00084 void QV3DCanvas::draw_center_of_rotation()
00085 {
00086
00087 glBegin(GL_LINES);
00088 glColor3ub(255,255,0);
00089
00090 glVertex3f(cx - 0.1,cy,cz);
00091 glVertex3f(cx + 0.1,cy,cz);
00092
00093 glVertex3f(cx,cy- 0.1,cz);
00094 glVertex3f(cx,cy+ 0.1,cz);
00095
00096 glVertex3f(cx,cy,cz- 0.1);
00097 glVertex3f(cx,cy,cz+ 0.1);
00098 glEnd();
00099 }
00100
00101 #define S 15
00102 void QV3DCanvas::paintGL()
00103 {
00104
00105 glMatrixMode(GL_PROJECTION);
00106 glLoadIdentity();
00107
00108
00109 qvGluPerspective(fov, (float)size().width()/(float)size().height(), 0.25, 100*zoom);
00110
00111
00112 glMatrixMode(GL_MODELVIEW);
00113 glLoadIdentity();
00114
00115
00116 qglClearColor(backgroundColor);
00117
00118
00119 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
00120
00121
00122 glEnable(GL_LIGHTING);
00123 glEnable(GL_LIGHT0);
00124 glEnable(GL_COLOR_MATERIAL);
00125
00126
00127 const GLfloat ambientLight[4] = {ambientLightR, ambientLightG, ambientLightB, 1.0 };
00128 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);
00129
00130
00131 foreach(QString name, getPropertyList())
00132 if (getPropertyFlags(name) & inputFlag)
00133 {
00134
00135 if (isType< QVImage<uChar,1> >(name)) {
00136 QVImage<uChar, 1> imageAux = getPropertyValue<QVImage<uChar,1> >(name);
00137 drawQVImage(&imageAux);
00138 }
00139
00140 else if (isType< QVImage<uChar,3> >(name)) {
00141 QVImage<uChar,3> imageAux = getPropertyValue<QVImage<uChar,3> >(name);
00142 drawQVImage(&imageAux);
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
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
00188 }
00189
00190 glTranslatef(0,0,-8*zoom);
00191
00192 const QVMatrix R = (trackballQuat.toRotationMatrix() | QVVector(3,0.0)) & (QVVector(3,0.0) << 1);
00193
00194 glMultMatrixd(R.getReadData());
00195
00196 glTranslatef(-cx,-cy,-cz);
00197
00198 display();
00199
00200 viewer();
00201
00202 if(dr_center)
00203 draw_center_of_rotation();
00204
00205
00206 glFlush();
00207 }
00208
00209 void QV3DCanvas::resizeGL( int w, int h )
00210 {
00211 glViewport(0,0,w,h);
00212 reshape(w,h);
00213
00214 glScaled((GLdouble)0.5,(GLdouble)0.5,(GLdouble)0.5);
00215
00216 viewer();
00217
00218 glFlush();
00219 }
00220
00224
00225 void QV3DCanvas::mousePressEvent(QMouseEvent *event)
00226 {
00227 beginx = event->x();
00228 beginy = event->y();
00229 if(event->button() == Qt::LeftButton) {
00230 pressedleft = TRUE;
00231 } else if(event->button() == Qt::RightButton) {
00232 pressedright = TRUE;
00233 }
00234 }
00235
00236 void QV3DCanvas::mouseReleaseEvent(QMouseEvent *event)
00237 {
00238 if(event->button() == Qt::LeftButton) {
00239 pressedleft = FALSE;
00240 } else if(event->button() == Qt::RightButton) {
00241 pressedright = FALSE;
00242 }
00243 }
00244
00245 void QV3DCanvas::mouseMoveEvent(QMouseEvent *event)
00246 {
00247 int x,y;
00248
00249 x = (int) event->x();
00250 y = (int) event->y();
00251
00252 if (pressedleft) {
00253 QVQuaternion spinQuat = QVQuaternion::trackball(
00254 (2.0*beginx - size().width()) / size().width(),
00255 (size().height() - 2.0*beginy) / size().height(),
00256 (2.0*x - size().width()) / size().width(),
00257 (size().height() - 2.0*y) / size().height());
00258
00259 trackballQuat = trackballQuat * spinQuat;
00260 updateGL();
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 beginx = x;
00272 beginy = y;
00273 }
00274
00275 void QV3DCanvas::wheelEvent(QWheelEvent *event)
00276 {
00277 zoom *= pow(0.9995,event->delta());
00278 updateGL();
00279 }
00280
00281 void QV3DCanvas::keyPressEvent(QKeyEvent *event)
00282 {
00283
00284 switch(event->key()) {
00285 case Qt::Key_Left:
00286 cx -= 0.1;
00287 break;
00288 case Qt::Key_Right:
00289 cx += 0.1;
00290 break;
00291 case Qt::Key_Up:
00292 cy += 0.1;
00293 break;
00294 case Qt::Key_Down:
00295 cy -= 0.1;
00296 break;
00297 case Qt::Key_PageUp:
00298 cz += 0.1;
00299 break;
00300 case Qt::Key_PageDown:
00301 cz -= 0.1;
00302 break;
00303 case 'C':
00304 dr_center = not dr_center;
00305 break;
00306
00307
00308
00309 }
00310
00311 updateGL();
00312 }
00313
00314 void QV3DCanvas::closeEvent(QCloseEvent * event)
00315 {
00316 Q_UNUSED(event);
00317 emit closed();
00318 }
00319
00321 #include <iostream>
00322 void QV3DCanvas::viewer()
00323 {
00324 qDebug() << "QVImageCanvas::viewer()";
00325 readInputProperties();
00326
00327
00328 foreach(QString name, getPropertyList())
00329 if (getPropertyFlags(name) & inputFlag)
00330 {
00331
00332 if (isType< QV3DPolylineF >(name))
00333 draw( getPropertyValue< QV3DPolylineF >(name),
00334 getPropertyValue<QColor>("Color for " + name),
00335 getPropertyValue<double>("Size for " + name));
00336
00337 else if (isType< QList<QV3DPointF> >(name))
00338 draw( getPropertyValue< QList<QV3DPointF> >(name),
00339 getPropertyValue<QColor>("Color for " + name),
00340 getPropertyValue<double>("Size for " + name));
00341
00342 else if (isType< QList<QV3DPolylineF> >(name))
00343 foreach(QV3DPolylineF polyline, getPropertyValue< QList<QV3DPolylineF> >(name))
00344 draw( polyline,
00345 getPropertyValue<QColor>("Color for " + name));
00346 }
00347
00348 foreach(QV3DModel *model, models)
00349 model->updatePaint(*this);
00350
00351 qDebug() << "QVImageCanvas::viewer() -> return";
00352 }
00353
00354 void QV3DCanvas::draw(const QV3DPolylineF &qv3DPolyline, const QColor color, const double size)
00355 {
00356 glPointSize(size);
00357 glBegin(GL_LINES);
00358 qglColor(color);
00359 for (int i = 1; i < qv3DPolyline.size(); i++)
00360 {
00361 glVertex3f(qv3DPolyline[i].x(), qv3DPolyline[i].y(), qv3DPolyline[i].z());
00362 glVertex3f(qv3DPolyline[i-1].x(), qv3DPolyline[i-1].y(), qv3DPolyline[i-1].z());
00363 }
00364 glEnd();
00365 }
00366
00367 void QV3DCanvas::draw(const QList<QV3DPointF> &qv3DPointList, const QColor color, const double size)
00368 {
00369 glBegin(GL_POINTS);
00370 qglColor(color);
00371 glPointSize(size);
00372 foreach(QV3DPointF point, qv3DPointList) {
00373
00374 glVertex3f(point.x(), point.y(), point.z());
00375 }
00376 glEnd();
00377 }
00378
00379 bool QV3DCanvas::linkUnspecifiedInputProperty(QVPropertyContainer *sourceContainer, QString sourcePropName, LinkType linkType)
00380 {
00381 if (linkType == SynchronousLink)
00382 {
00383 std::cerr << "ERROR: QVImageCanvas::linkUnspecifiedInputProperty():"
00384 << " the linkType must be AsynchronousLink, the link will not be done"
00385 << std::endl;
00386 return false;
00387 }
00388
00389 QVProcessingBlock* block;
00390 if((block = dynamic_cast<QVProcessingBlock*>(sourceContainer)) != NULL)
00391 {
00392 std::cout << "QV3DCanvas: Adding property '" << qPrintable(sourcePropName) << "'" << std::endl;
00393 addPropertyFromQVariant(sourcePropName, inputFlag, block->getPropertyQVariantValue(sourcePropName), block->getPropertyInfo(sourcePropName));
00394 if ( block->isType< QV3DPolylineF >(sourcePropName) ||
00395 block->isType< QList<QV3DPointF> >(sourcePropName) ||
00396 block->isType< QList<QV3DPolylineF> >(sourcePropName) )
00397 {
00398 addProperty<QColor>("Color for " + sourcePropName, inputFlag, getNextColor(), QString("Color for object ") + sourcePropName);
00399 addProperty<double>("Size for " + sourcePropName, inputFlag, 1, QString("Size for object ") + sourcePropName);
00400 std::cout << "QV3DCanvas: Added property 'Color for " << qPrintable(sourcePropName) << "'" << std::endl;
00401 std::cout << "QV3DCanvas: Added property 'Size for " << qPrintable(sourcePropName) << "'" << std::endl;
00402 }
00403 bool result = block->linkProperty(sourcePropName, this, sourcePropName ,QVProcessingBlock::AsynchronousLink);
00404
00405 return result;
00406 }
00407 else
00408 {
00409 std::cerr << "ERROR: QVImageCanvas::linkUnspecifiedInputProperty(): the sourceContainer container must be a QVProcessingBlock, the link will not be done" << std::endl;
00410 return false;
00411 }
00412 }
00413
00414 void QV3DCanvas::drawQVImage(QVGenericImage *image)
00415 {
00416
00417 QVGenericImage *imagecopy=NULL;
00418 if(image->isCompatibleWith("QVImage<uChar,1>")) {
00419 imagecopy = new QVImage<uChar,1>;
00420 *(dynamic_cast<QVImage<uChar,1>*>(imagecopy)) = *(dynamic_cast<QVImage<uChar,1>*>(image));
00421 }
00422 else if(image->isCompatibleWith("QVImage<uChar,3>")) {
00423 imagecopy = new QVImage<uChar,3>;
00424 *(dynamic_cast<QVImage<uChar,3>*>(imagecopy)) = *(dynamic_cast<QVImage<uChar,3>*>(image));
00425 }
00426 else {
00427
00428 qFatal("Type of QVGenericImage still not supported in drawQVImage");
00429 }
00430
00432 const int cols = image->getCols(),
00433 rows = image->getRows();
00434
00435 setMinimumSize(cols,rows);
00436 setMaximumSize(cols,rows);
00437 resize(cols,rows);
00438
00439
00440
00441 glPushAttrib(GL_ALL_ATTRIB_BITS);
00442 glPushClientAttrib(GL_ALL_ATTRIB_BITS);
00443 glMatrixMode(GL_PROJECTION);
00444 glPushMatrix();
00445 glMatrixMode(GL_MODELVIEW);
00446 glPushMatrix();
00447
00448
00449
00450 glViewport(0,0,width(),height());
00451 glMatrixMode(GL_PROJECTION);
00452 glLoadIdentity();
00453
00454 glOrtho(0, cols, rows,0,-1,1);
00455 glMatrixMode(GL_MODELVIEW);
00456 glLoadIdentity();
00457
00458
00459 const QRect final_rect = QRect(imagecopy->getAnchor()+imagecopy->getROI().topLeft(),
00460 QSize(imagecopy->getROI().width(),imagecopy->getROI().height()));
00461
00462
00463
00464
00465
00466
00467 glRasterPos2f(0.0 , 0.0);
00468 glBitmap(0, 0, 0.0, 0.0, 0.0, 0.0, NULL);
00469 glPixelZoom(1.0,-1.0);
00470
00471
00472
00473 int img_step = imagecopy->getStep();
00474
00475
00476
00477
00478
00479
00480
00481
00482 if(image->isCompatibleWith("QVImage<uChar,1>"))
00483 {
00484 glPixelStorei(GL_UNPACK_ROW_LENGTH, img_step);
00485 glDrawPixels(cols, rows, GL_LUMINANCE, GL_UNSIGNED_BYTE, static_cast<QVImage<uchar,1> *>(imagecopy)->getReadData());
00486 }
00487 else if(image->isCompatibleWith("QVImage<uChar,3>"))
00488 {
00489 glPixelStorei(GL_UNPACK_ROW_LENGTH, img_step/3);
00490 glDrawPixels(cols, rows, GL_RGB, GL_UNSIGNED_BYTE, static_cast<QVImage<uchar,3> *>(imagecopy)->getReadData());
00491 }
00492 else
00493 qFatal("Type of QVGenericImage still not supported in drawQVImage");
00494
00495
00496
00497 glPopClientAttrib();
00498 glPopAttrib();
00499 glMatrixMode(GL_MODELVIEW);
00500 glPopMatrix();
00501 glMatrixMode(GL_PROJECTION);
00502 glPopMatrix();
00503 }
00504
00505 void QV3DEllipsoid::paint(QV3DCanvas &glWidget)
00506 {
00507 glWidget.qglColor(color);
00508
00509 for(int i = 0; i <= lats; i++)
00510 {
00511 double lat0 = M_PI * (-0.5 + (double) (i - 1) / lats);
00512 double z0 = sin(lat0);
00513 double zr0 = cos(lat0);
00514
00515 double lat1 = M_PI * (-0.5 + (double) i / lats);
00516 double z1 = sin(lat1);
00517 double zr1 = cos(lat1);
00518
00519 glBegin(GL_QUAD_STRIP);
00520 for(int j = 0; j <= longs; j++)
00521 {
00522 double lng = 2 * M_PI * (double) (j - 1) / longs;
00523 double x = cos(lng);
00524 double y = sin(lng);
00525
00526 glNormal3f(rx * x * zr0 + cx, ry * y * zr0 + cy, rz * z0 + cz);
00527 glVertex3f(rx * x * zr0 + cx, ry * y * zr0 + cy, rz * z0 + cz);
00528 glNormal3f(rx * x * zr1 + cx, ry * y * zr1 + cy, rz * z1 + cz);
00529 glVertex3f(rx * x * zr1 + cx, ry * y * zr1 + cy, rz * z1 + cz);
00530 }
00531 glEnd();
00532 }
00533 };
00534
00535
00536 #endif
00537