00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "viewer/qt/QtViewer.h"
00028 #include <sofa/helper/system/FileRepository.h>
00029 #include <sofa/helper/system/thread/CTime.h>
00030 #include <sofa/simulation/tree/Simulation.h>
00031 #include <sofa/core/objectmodel/KeypressedEvent.h>
00032 #include <sofa/core/objectmodel/KeyreleasedEvent.h>
00033 #include <sofa/core/ObjectFactory.h>
00034
00035 #include <math.h>
00036 #include <iostream>
00037 #include <fstream>
00038 #include <string.h>
00039 #include <math.h>
00040
00041 #include <qevent.h>
00042 #include "GenGraphForm.h"
00043 #include "Main.h"
00044
00045 #include <sofa/helper/system/glut.h>
00046 #include <sofa/helper/gl/glfont.h>
00047 #include <sofa/helper/gl/RAII.h>
00048 #ifdef SOFA_HAVE_GLEW
00049 #include <sofa/helper/gl/GLSLShader.h>
00050 #endif
00051 #include <sofa/helper/io/ImageBMP.h>
00052
00053
00054 #include <sofa/defaulttype/RigidTypes.h>
00055
00056
00057
00058
00059
00060
00061 namespace sofa
00062 {
00063
00064 namespace gui
00065 {
00066
00067 namespace qt
00068 {
00069
00070 namespace viewer
00071 {
00072
00073 namespace qt
00074 {
00075 using std::cout;
00076 using std::endl;
00077 using namespace sofa::defaulttype;
00078 using namespace sofa::helper::gl;
00079
00080
00081 using sofa::simulation::tree::getSimulation;
00082
00083
00084
00085
00086
00087
00088 bool QtViewer::_mouseTrans = false;
00089 bool QtViewer::_mouseRotate = false;
00090 Quaternion QtViewer::_mouseInteractorNewQuat;
00091 Quaternion QtViewer::_newQuat;
00092 Quaternion QtViewer::_currentQuat;
00093 Vector3 QtViewer::_mouseInteractorRelativePosition(0,0,0);
00094
00095 #ifdef SOFA_HAVE_GLEW
00096
00097
00098
00099 enum { SHADOW_WIDTH = 512 };
00100 enum { SHADOW_HEIGHT = 512 };
00101 enum { SHADOW_MASK_SIZE = 2048 };
00102
00103
00104
00105 #define GL_TEXTURE_COMPARE_MODE_ARB 0x884C
00106
00107
00108
00109 #define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D
00110
00111
00112 #define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E
00113
00114
00115 GLuint g_DepthTexture;
00116
00117
00118 GLSLShader g_Shader;
00119
00120
00121 float g_DepthOffset[2] = { 10.0f, 0.0f };
00122 float g_DepthBias[2] = { 0.0f, 0.0f };
00123
00124
00125 float g_mProjection[16] = {0};
00126 float g_mModelView[16] = {0};
00127
00128
00129 GLuint ShadowTextureMask;
00130
00131
00132 #endif // SOFA_HAVE_GLEW
00133
00134 static bool enabled = false;
00135 sofa::core::ObjectFactory::ClassEntry* classVisualModel;
00136
00140 int QtViewer::EnableViewer()
00141 {
00142 if (!enabled)
00143 {
00144 enabled = true;
00145
00146 sofa::core::ObjectFactory::AddAlias("VisualModel", "OglModel", true, &classVisualModel);
00147 }
00148 return 0;
00149 }
00150
00154 int QtViewer::DisableViewer()
00155 {
00156 if (enabled)
00157 {
00158 enabled = false;
00159 sofa::core::ObjectFactory::ResetAlias("VisualModel", classVisualModel);
00160 }
00161 return 0;
00162 }
00163
00164
00165
00166
00167 QtViewer::QtViewer(QWidget* parent, const char* name)
00168 : QGLWidget(parent, name)
00169 {
00170
00171
00172 groot = NULL;
00173 initTexturesDone = false;
00174
00175
00176 timerAnimate = new QTimer(this);
00177
00178
00179 _previousEyePos = Vector3(0.0, 0.0, 0.0);
00180 _zoom = 1.0;
00181 _zoomSpeed = 250.0;
00182 _panSpeed = 25.0;
00183 _navigationMode = TRACKBALL_MODE;
00184 _spinning = false;
00185 _moving = false;
00186 _video = false;
00187 _axis = false;
00188 _background = 0;
00189 _shadow = false;
00190 _gl_shadow = false;
00191 _numOBJmodels = 0;
00192 _materialMode = 0;
00193 _facetNormal = GL_FALSE;
00194 _renderingMode = GL_RENDER;
00195 _waitForRender = false;
00196 sceneBBoxIsValid = false;
00197 texLogo = NULL;
00198
00199
00200
00201
00202
00203
00204
00205 _arrow = gluNewQuadric();
00206 gluQuadricDrawStyle(_arrow, GLU_FILL);
00207 gluQuadricOrientation(_arrow, GLU_OUTSIDE);
00208 gluQuadricNormals(_arrow, GLU_SMOOTH);
00209
00210 _tube = gluNewQuadric();
00211 gluQuadricDrawStyle(_tube, GLU_FILL);
00212 gluQuadricOrientation(_tube, GLU_OUTSIDE);
00213 gluQuadricNormals(_tube, GLU_SMOOTH);
00214
00215 _sphere = gluNewQuadric();
00216 gluQuadricDrawStyle(_sphere, GLU_FILL);
00217 gluQuadricOrientation(_sphere, GLU_OUTSIDE);
00218 gluQuadricNormals(_sphere, GLU_SMOOTH);
00219
00220 _disk = gluNewQuadric();
00221 gluQuadricDrawStyle(_disk, GLU_FILL);
00222 gluQuadricOrientation(_disk, GLU_OUTSIDE);
00223 gluQuadricNormals(_disk, GLU_SMOOTH);
00224
00225
00226 _newTrackball.ComputeQuaternion(0.0, 0.0, 0.0, 0.0);
00227 _newQuat = _newTrackball.GetQuaternion();
00228
00230
00232 m_isControlPressed = false;
00233 _mouseInteractorMoving = false;
00234 _mouseInteractorTranslationMode = false;
00235 _mouseInteractorRotationMode = false;
00236 _mouseInteractorSavedPosX = 0;
00237 _mouseInteractorSavedPosY = 0;
00238 _mouseInteractorTrackball.ComputeQuaternion(0.0, 0.0, 0.0, 0.0);
00239 _mouseInteractorNewQuat = _mouseInteractorTrackball.GetQuaternion();
00240
00241 interactor = NULL;
00242
00243 }
00244
00245
00246
00247
00248
00249 QtViewer::~QtViewer()
00250 {
00251 }
00252
00253
00254
00255
00256
00257 void QtViewer::initializeGL(void)
00258 {
00259 static GLfloat specref[4];
00260 static GLfloat ambientLight[4];
00261 static GLfloat diffuseLight[4];
00262 static GLfloat specular[4];
00263 static GLfloat lmodel_ambient[] ={0.0f, 0.0f, 0.0f, 0.0f};
00264 static GLfloat lmodel_twoside[] ={GL_FALSE};
00265 static GLfloat lmodel_local[] ={GL_FALSE};
00266 bool initialized = false;
00267
00268 if (!initialized)
00269 {
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 _lightPosition[0] = -0.7f;
00280 _lightPosition[1] = 0.3f;
00281 _lightPosition[2] = 0.0f;
00282 _lightPosition[3] = 1.0f;
00283
00284 ambientLight[0] = 0.5f;
00285 ambientLight[1] = 0.5f;
00286 ambientLight[2] = 0.5f;
00287 ambientLight[3] = 1.0f;
00288
00289 diffuseLight[0] = 0.9f;
00290 diffuseLight[1] = 0.9f;
00291 diffuseLight[2] = 0.9f;
00292 diffuseLight[3] = 1.0f;
00293
00294 specular[0] = 1.0f;
00295 specular[1] = 1.0f;
00296 specular[2] = 1.0f;
00297 specular[3] = 1.0f;
00298
00299 specref[0] = 1.0f;
00300 specref[1] = 1.0f;
00301 specref[2] = 1.0f;
00302 specref[3] = 1.0f;
00303
00304
00305 #ifdef SOFA_HAVE_GLEW
00306 glewInit();
00307 if (!GLEW_ARB_multitexture)
00308 std::cerr << "Error: GL_ARB_multitexture not supported\n";
00309 #endif
00310
00311 _clearBuffer = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
00312 _lightModelTwoSides = false;
00313
00314 glDepthFunc(GL_LEQUAL);
00315 glClearDepth(1.0);
00316 glEnable(GL_NORMALIZE);
00317
00318 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
00319
00320
00321 glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_local);
00322 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
00323 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
00324
00325
00326 glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
00327 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
00328 glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
00329 glLightfv(GL_LIGHT0, GL_POSITION, _lightPosition);
00330
00331
00332 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
00333
00334
00335 glMaterialfv(GL_FRONT, GL_SPECULAR, specref);
00336 glMateriali(GL_FRONT, GL_SHININESS, 128);
00337
00338 glShadeModel(GL_SMOOTH);
00339
00340
00341
00342
00343
00344
00345 texLogo = new helper::gl::Texture(new helper::io::ImageBMP( sofa::helper::system::DataRepository.getFile("textures/SOFA_logo.bmp")));
00346 texLogo->init();
00347
00348 glEnableClientState(GL_VERTEX_ARRAY);
00349
00350
00351
00352
00353 glEnable(GL_LIGHT0);
00354
00355
00356 #ifdef SOFA_HAVE_GLEW
00357
00358 CreateRenderTexture(g_DepthTexture, SHADOW_WIDTH, SHADOW_HEIGHT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT);
00359 CreateRenderTexture(ShadowTextureMask, SHADOW_MASK_SIZE, SHADOW_MASK_SIZE, GL_LUMINANCE, GL_LUMINANCE);
00360
00361 if ( GLSLShader::InitGLSL() )
00362 {
00363
00364 g_Shader.InitShaders(sofa::helper::system::DataRepository.getFile("shaders/ShadowMappingPCF.vert"), sofa::helper::system::DataRepository.getFile("shaders/ShadowMappingPCF.frag"));
00365 _gl_shadow = true;
00366 }
00367 else
00368 #endif
00369 {
00370 printf("WARNING QtViewer : shadows are not supported !\n");
00371 _gl_shadow=false;
00372 }
00373
00374
00375 initialized = true;
00376
00377 _beginTime = CTime::getTime();
00378
00379 printf("GL initialized\n");
00380 }
00381
00382
00383 resetView();
00384 }
00385
00386
00387
00388
00389
00395
00396 void QtViewer::StoreLightMatrices()
00397 {
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 memset(g_mModelView, 0, sizeof(float)*16);
00408 memset(g_mProjection, 0, sizeof(float)*16);
00409
00410 g_mModelView[0] = 1;
00411 g_mModelView[5] = 1;
00412 g_mModelView[10] = 1;
00413 g_mModelView[15] = 1;
00414
00415
00416
00417
00418 float lx = -_lightPosition[0] * lastProjectionMatrix[0] - _lightPosition[1] * lastProjectionMatrix[4] + lastProjectionMatrix[12];
00419 float ly = -_lightPosition[0] * lastProjectionMatrix[1] - _lightPosition[1] * lastProjectionMatrix[5] + lastProjectionMatrix[13];
00420 float lz = -_lightPosition[0] * lastProjectionMatrix[2] - _lightPosition[1] * lastProjectionMatrix[6] + lastProjectionMatrix[14];
00421
00422
00423
00424 Vector3 l(-lx,-ly,-lz);
00425 Vector3 y;
00426 y = l.cross(Vector3(1,0,0));
00427 Vector3 x;
00428 x = y.cross(l);
00429 l.normalize();
00430 y.normalize();
00431 x.normalize();
00432
00433 g_mProjection[ 0] = x[0]; g_mProjection[ 4] = x[1]; g_mProjection[ 8] = x[2]; g_mProjection[12] = 0;
00434 g_mProjection[ 1] = y[0]; g_mProjection[ 5] = y[1]; g_mProjection[ 9] = y[2]; g_mProjection[13] = 0;
00435 g_mProjection[ 2] = l[0]; g_mProjection[ 6] = l[1]; g_mProjection[10] = l[2]; g_mProjection[14] = 0;
00436 g_mProjection[ 3] = 0; g_mProjection[ 7] = 0; g_mProjection[11] = 0; g_mProjection[15] = 1;
00437
00438 g_mProjection[ 0] = x[0]; g_mProjection[ 4] = y[0]; g_mProjection[ 8] = l[0]; g_mProjection[12] = 0;
00439 g_mProjection[ 1] = x[1]; g_mProjection[ 5] = y[1]; g_mProjection[ 9] = l[1]; g_mProjection[13] = 0;
00440 g_mProjection[ 2] = x[2]; g_mProjection[ 6] = y[2]; g_mProjection[10] = l[2]; g_mProjection[14] = 0;
00441 g_mProjection[ 3] = 0; g_mProjection[ 7] = 0; g_mProjection[11] = 0; g_mProjection[15] = 1;
00442
00443 glPushMatrix();{
00444
00445 glLoadIdentity();
00446 glScaled(1.0/(fabs(g_mProjection[0])+fabs(g_mProjection[4])+fabs(g_mProjection[8])),
00447 1.0/(fabs(g_mProjection[1])+fabs(g_mProjection[5])+fabs(g_mProjection[9])),
00448 1.0/(fabs(g_mProjection[2])+fabs(g_mProjection[6])+fabs(g_mProjection[10])));
00449 glMultMatrixf(g_mProjection);
00450 glMultMatrixd(lastProjectionMatrix);
00451
00452
00453 glGetFloatv(GL_MODELVIEW_MATRIX, g_mProjection);
00454
00455
00456 }glPopMatrix();
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 }
00485
00491
00492 void QtViewer::CreateRenderTexture(GLuint& textureID, int sizeX, int sizeY, int channels, int type)
00493 {
00494 glGenTextures(1, &textureID);
00495 glBindTexture(GL_TEXTURE_2D, textureID);
00496
00497
00498 glTexImage2D(GL_TEXTURE_2D, 0, channels, sizeX, sizeY, 0, type, GL_UNSIGNED_INT, NULL);
00499
00500
00501 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
00502 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
00503 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00504 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00505 }
00506
00512
00513 void QtViewer::ApplyShadowMap()
00514 {
00515 #ifdef SOFA_HAVE_GLEW
00516
00517 g_Shader.TurnOn();
00518
00519
00520 glActiveTextureARB(GL_TEXTURE1_ARB);
00521 glEnable(GL_TEXTURE_2D);
00522 glBindTexture(GL_TEXTURE_2D, g_DepthTexture);
00523
00524
00525 g_Shader.SetInt(g_Shader.GetVariable("shadowMap"), 1);
00526
00527
00528
00529
00530 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00531 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00532 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00533 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00534 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB,
00535 GL_COMPARE_R_TO_TEXTURE_ARB);
00536
00537
00538
00539
00540 const float mBias[] = {0.5, 0.0, 0.0, 0.0,
00541 0.0, 0.5, 0.0, 0.0,
00542 0.0, 0.0, 0.5+g_DepthBias[0], 0.0,
00543 0.5, 0.5, 0.5+g_DepthBias[1], 1.0};
00544
00545 glMatrixMode(GL_TEXTURE);
00546
00547 glLoadMatrixf(mBias);
00548 glMultMatrixf(g_mProjection);
00549 glMultMatrixf(g_mModelView);
00550
00551
00552 glMatrixMode(GL_MODELVIEW);
00553
00554 glActiveTextureARB(GL_TEXTURE0_ARB);
00555
00556
00557
00558 glPushMatrix();
00559 {
00560 glLoadIdentity();
00561 _sceneTransform.Apply();
00562 glGetDoublev(GL_MODELVIEW_MATRIX,lastModelviewMatrix);
00563 DisplayOBJs();
00564 }
00565 glPopMatrix();
00566
00567
00568 glMatrixMode(GL_TEXTURE);
00569 glLoadIdentity();
00570 glMatrixMode(GL_MODELVIEW);
00571
00572
00573
00574 glActiveTextureARB(GL_TEXTURE1_ARB);
00575 glDisable(GL_TEXTURE_2D);
00576 glActiveTextureARB(GL_TEXTURE0_ARB);
00577
00578
00579 g_Shader.TurnOff();
00580 #endif
00581 }
00582
00583
00584
00585
00586 void QtViewer::PrintString(void* font, char* string)
00587 {
00588 int len, i;
00589
00590 len = (int) strlen(string);
00591 for (i = 0; i < len; i++)
00592 {
00593 glutBitmapCharacter(font, string[i]);
00594 }
00595 }
00596
00597
00598
00599
00600 void QtViewer::Display3DText(float x, float y, float z, char* string)
00601 {
00602 char* c;
00603
00604 glPushMatrix();
00605 glTranslatef(x, y, z);
00606 for (c = string; *c != '\0'; c++)
00607 {
00608 glutStrokeCharacter(GLUT_STROKE_ROMAN, *c);
00609 }
00610 glPopMatrix();
00611 }
00612
00613
00614
00615
00616
00617 void QtViewer::DrawAxis(double xpos, double ypos, double zpos,
00618 double arrowSize)
00619 {
00620 float fontScale = (float) (arrowSize / 600.0);
00621
00622 Enable<GL_DEPTH_TEST> depth;
00623 Enable<GL_LIGHTING> lighting;
00624 Enable<GL_COLOR_MATERIAL> colorMat;
00625
00626 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00627 glShadeModel(GL_SMOOTH);
00628
00629
00630 glPushMatrix();
00631 glColor3f(1.0, 0.0, 0.0);
00632 glTranslated(xpos, ypos, zpos);
00633 glRotatef(90.0f, 0.0, 1.0, 0.0);
00634 gluCylinder(_tube, arrowSize / 50.0, arrowSize / 50.0, arrowSize, 10, 10);
00635 glTranslated(0.0, 0.0, arrowSize);
00636 gluCylinder(_arrow, arrowSize / 15.0, 0.0, arrowSize / 5.0, 10, 10);
00637
00638 glTranslated(-0.5 * fontScale * (double)
00639 glutStrokeWidth(GLUT_STROKE_ROMAN, 88),
00640 arrowSize / 15.0, arrowSize /
00641 5.0);
00642 glLineWidth(3.0);
00643 glScalef(fontScale, fontScale, fontScale);
00644 glutStrokeCharacter(GLUT_STROKE_ROMAN, 88);
00645 glScalef(1.0f / fontScale, 1.0f / fontScale, 1.0f / fontScale);
00646 glLineWidth(1.0f);
00647
00648 glTranslated(-xpos, -ypos, -zpos);
00649 glPopMatrix();
00650
00651
00652 glPushMatrix();
00653 glColor3f(0.0, 1.0, 0.0);
00654 glTranslated(xpos, ypos, zpos);
00655 glRotatef(-90.0f, 1.0, 0.0, 0.0);
00656 gluCylinder(_tube, arrowSize / 50.0, arrowSize / 50.0, arrowSize, 10, 10);
00657 glTranslated(0.0, 0.0, arrowSize);
00658 gluCylinder(_arrow, arrowSize / 15.0, 0.0, arrowSize / 5.0, 10, 10);
00659
00660 glTranslated(-0.5 * fontScale * (double)
00661 glutStrokeWidth(GLUT_STROKE_ROMAN, 89),
00662 arrowSize / 15.0, arrowSize /
00663 5.0);
00664 glLineWidth(3.0);
00665 glScalef(fontScale, fontScale, fontScale);
00666 glutStrokeCharacter(GLUT_STROKE_ROMAN, 89);
00667 glScalef(1.0f / fontScale, 1.0f / fontScale, 1.0f / fontScale);
00668 glLineWidth(1.0);
00669
00670 glTranslated(-xpos, -ypos, -zpos);
00671 glPopMatrix();
00672
00673
00674 glPushMatrix();
00675 glColor3f(0.0, 0.0, 1.0);
00676 glTranslated(xpos, ypos, zpos);
00677 glRotatef(0.0f, 1.0, 0.0, 0.0);
00678 gluCylinder(_tube, arrowSize / 50.0, arrowSize / 50.0, arrowSize, 10, 10);
00679 glTranslated(0.0, 0.0, arrowSize);
00680 gluCylinder(_arrow, arrowSize / 15.0, 0.0, arrowSize / 5.0, 10, 10);
00681
00682 glTranslated(-0.5 * fontScale * (double)
00683 glutStrokeWidth(GLUT_STROKE_ROMAN, 90),
00684 arrowSize / 15.0, arrowSize /
00685 5.0);
00686 glLineWidth(3.0);
00687 glScalef(fontScale, fontScale, fontScale);
00688 glutStrokeCharacter(GLUT_STROKE_ROMAN, 90);
00689 glScalef(1.0f / fontScale, 1.0f / fontScale, 1.0f / fontScale);
00690 glLineWidth(1.0);
00691
00692 glTranslated(-xpos, -ypos, -zpos);
00693 glPopMatrix();
00694 }
00695
00696
00697
00698
00699
00700 void QtViewer::DrawBox(SReal* minBBox, SReal* maxBBox, SReal r)
00701 {
00702
00703 if (r==0.0)
00704 r = (Vector3(maxBBox) - Vector3(minBBox)).norm() / 500;
00705 #if 0
00706 {
00707 Enable<GL_DEPTH_TEST> depth;
00708 Disable<GL_LIGHTING> lighting;
00709 glColor3f(0.0, 1.0, 1.0);
00710 glBegin(GL_LINES);
00711 for (int corner=0; corner<4; ++corner)
00712 {
00713 glVertex3d( minBBox[0] ,
00714 (corner&1)?minBBox[1]:maxBBox[1],
00715 (corner&2)?minBBox[2]:maxBBox[2]);
00716 glVertex3d( maxBBox[0] ,
00717 (corner&1)?minBBox[1]:maxBBox[1],
00718 (corner&2)?minBBox[2]:maxBBox[2]);
00719 }
00720 for (int corner=0; corner<4; ++corner)
00721 {
00722 glVertex3d((corner&1)?minBBox[0]:maxBBox[0],
00723 minBBox[1] ,
00724 (corner&2)?minBBox[2]:maxBBox[2]);
00725 glVertex3d((corner&1)?minBBox[0]:maxBBox[0],
00726 maxBBox[1] ,
00727 (corner&2)?minBBox[2]:maxBBox[2]);
00728 }
00729
00730
00731 for (int corner=0; corner<4; ++corner)
00732 {
00733 glVertex3d((corner&1)?minBBox[0]:maxBBox[0],
00734 (corner&2)?minBBox[1]:maxBBox[1],
00735 minBBox[2] );
00736 glVertex3d((corner&1)?minBBox[0]:maxBBox[0],
00737 (corner&2)?minBBox[1]:maxBBox[1],
00738 maxBBox[2] );
00739 }
00740 glEnd();
00741 return;
00742 }
00743 #endif
00744 Enable<GL_DEPTH_TEST> depth;
00745 Enable<GL_LIGHTING> lighting;
00746 Enable<GL_COLOR_MATERIAL> colorMat;
00747
00748 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00749 glShadeModel(GL_SMOOTH);
00750
00751
00752 glColor3f(0.0, 1.0, 1.0);
00753 for (int corner=0; corner<8; ++corner)
00754 {
00755 glPushMatrix();
00756 glTranslated((corner&1)?minBBox[0]:maxBBox[0],
00757 (corner&2)?minBBox[1]:maxBBox[1],
00758 (corner&4)?minBBox[2]:maxBBox[2]);
00759 gluSphere(_sphere,2*r,20,10);
00760 glPopMatrix();
00761 }
00762
00763 glColor3f(1.0, 1.0, 0.0);
00764
00765 for (int corner=0; corner<4; ++corner)
00766 {
00767 glPushMatrix();
00768 glTranslated( minBBox[0] ,
00769 (corner&1)?minBBox[1]:maxBBox[1],
00770 (corner&2)?minBBox[2]:maxBBox[2]);
00771 glRotatef(90,0,1,0);
00772 gluCylinder(_tube, r, r, maxBBox[0] - minBBox[0], 10, 10);
00773 glPopMatrix();
00774 }
00775
00776
00777 for (int corner=0; corner<4; ++corner)
00778 {
00779 glPushMatrix();
00780 glTranslated((corner&1)?minBBox[0]:maxBBox[0],
00781 minBBox[1] ,
00782 (corner&2)?minBBox[2]:maxBBox[2]);
00783 glRotatef(-90,1,0,0);
00784 gluCylinder(_tube, r, r, maxBBox[1] - minBBox[1], 10, 10);
00785 glPopMatrix();
00786 }
00787
00788
00789 for (int corner=0; corner<4; ++corner)
00790 {
00791 glPushMatrix();
00792 glTranslated((corner&1)?minBBox[0]:maxBBox[0],
00793 (corner&2)?minBBox[1]:maxBBox[1],
00794 minBBox[2] );
00795 gluCylinder(_tube, r, r, maxBBox[2] - minBBox[2], 10, 10);
00796 glPopMatrix();
00797 }
00798 }
00799
00800
00801
00802
00803
00804
00805 void QtViewer::DrawXYPlane(double zo, double xmin, double xmax, double ymin,
00806 double ymax, double step)
00807 {
00808 register double x, y;
00809
00810 Enable<GL_DEPTH_TEST> depth;
00811
00812 glBegin(GL_LINES);
00813 for (x = xmin; x <= xmax; x += step)
00814 {
00815 glVertex3d(x, ymin, zo);
00816 glVertex3d(x, ymax, zo);
00817 }
00818 glEnd();
00819
00820 glBegin(GL_LINES);
00821 for (y = ymin; y <= ymax; y += step)
00822 {
00823 glVertex3d(xmin, y, zo);
00824 glVertex3d(xmax, y, zo);
00825 }
00826 glEnd();
00827 }
00828
00829
00830
00831
00832
00833
00834 void QtViewer::DrawYZPlane(double xo, double ymin, double ymax, double zmin,
00835 double zmax, double step)
00836 {
00837 register double y, z;
00838 Enable<GL_DEPTH_TEST> depth;
00839
00840 glBegin(GL_LINES);
00841 for (y = ymin; y <= ymax; y += step)
00842 {
00843 glVertex3d(xo, y, zmin);
00844 glVertex3d(xo, y, zmax);
00845 }
00846 glEnd();
00847
00848 glBegin(GL_LINES);
00849 for (z = zmin; z <= zmax; z += step)
00850 {
00851 glVertex3d(xo, ymin, z);
00852 glVertex3d(xo, ymax, z);
00853 }
00854 glEnd();
00855
00856 }
00857
00858
00859
00860
00861
00862
00863 void QtViewer::DrawXZPlane(double yo, double xmin, double xmax, double zmin,
00864 double zmax, double step)
00865 {
00866 register double x, z;
00867 Enable<GL_DEPTH_TEST> depth;
00868
00869 glBegin(GL_LINES);
00870 for (x = xmin; x <= xmax; x += step)
00871 {
00872 glVertex3d(x, yo, zmin);
00873 glVertex3d(x, yo, zmax);
00874 }
00875 glEnd();
00876
00877 glBegin(GL_LINES);
00878 for (z = zmin; z <= zmax; z += step)
00879 {
00880 glVertex3d(xmin, yo, z);
00881 glVertex3d(xmax, yo, z);
00882 }
00883 glEnd();
00884 }
00885
00886
00887
00888
00889 void QtViewer::DrawLogo()
00890 {
00891 int w = 0;
00892 int h = 0;
00893
00894 if (texLogo && texLogo->getImage()) {
00895 h = texLogo->getImage()->getHeight();
00896 w = texLogo->getImage()->getWidth();
00897 }
00898 else return;
00899
00900 Enable <GL_TEXTURE_2D> tex;
00901 glDisable(GL_DEPTH_TEST);
00902 glMatrixMode(GL_PROJECTION);
00903 glPushMatrix();
00904 glLoadIdentity();
00905 glOrtho(-0.5, _W, -0.5, _H, -1.0, 1.0);
00906 glMatrixMode(GL_MODELVIEW);
00907 glLoadIdentity();
00908
00909 if (texLogo)
00910 texLogo->bind();
00911
00912 glColor3f(1.0f, 1.0f, 1.0f);
00913 glBegin(GL_QUADS);
00914 glTexCoord2d(0.0, 0.0);
00915 glVertex3d((_W-w)/2, (_H-h)/2, 0.0);
00916
00917 glTexCoord2d(1.0, 0.0);
00918 glVertex3d( _W-(_W-w)/2, (_H-h)/2, 0.0);
00919
00920 glTexCoord2d(1.0, 1.0);
00921 glVertex3d( _W-(_W-w)/2, _H-(_H-h)/2, 0.0);
00922
00923 glTexCoord2d(0.0, 1.0);
00924 glVertex3d((_W-w)/2, _H-(_H-h)/2, 0.0);
00925 glEnd();
00926
00927 glBindTexture(GL_TEXTURE_2D, 0);
00928
00929 glMatrixMode(GL_PROJECTION);
00930 glPopMatrix();
00931 glMatrixMode(GL_MODELVIEW);
00932 }
00933
00934
00935
00936
00937 void QtViewer::DisplayOBJs(bool shadowPass)
00938 {
00939 if (!groot) return;
00940 Enable<GL_LIGHTING> light;
00941 Enable<GL_DEPTH_TEST> depth;
00942
00943 glShadeModel(GL_SMOOTH);
00944
00945 glColor4f(1,1,1,1);
00946 glDisable(GL_COLOR_MATERIAL);
00947
00948 if (!initTexturesDone)
00949 {
00950
00951
00952 getSimulation()->initTextures(groot);
00953
00954 initTexturesDone = true;
00955 }
00956
00957
00958 {
00959 if (shadowPass)
00960 getSimulation()->drawShadows(groot);
00961 else
00962 getSimulation()->draw(groot);
00963 if (_axis)
00964 {
00965 DrawAxis(0.0, 0.0, 0.0, 10.0);
00966 if (sceneMinBBox[0] < sceneMaxBBox[0])
00967 DrawBox(sceneMinBBox.ptr(), sceneMaxBBox.ptr());
00968 }
00969 }
00970
00971
00972
00973 }
00974
00975
00976
00977
00978 void QtViewer::DisplayMenu(void)
00979 {
00980 Disable<GL_LIGHTING> light;
00981
00982 glMatrixMode(GL_PROJECTION);
00983 glPushMatrix();
00984 glLoadIdentity();
00985 glOrtho(-0.5, _W, -0.5, _H, -1.0, 1.0);
00986 glMatrixMode(GL_MODELVIEW);
00987 glPushMatrix();
00988 glLoadIdentity();
00989
00990 glColor3f(0.3f, 0.7f, 0.95f);
00991 glRasterPos2i(_W / 2 - 5, _H - 15);
00992
00993
00994
00995 glMatrixMode(GL_PROJECTION);
00996 glPopMatrix();
00997 glMatrixMode(GL_MODELVIEW);
00998 glPopMatrix();
00999 }
01000
01001
01002
01003
01004 void QtViewer::DrawScene(void)
01005 {
01006
01007 _newQuat.buildRotationMatrix(_sceneTransform.rotation);
01008 calcProjection();
01009
01010 #ifdef SOFA_HAVE_GLEW
01011 if (_shadow)
01012 {
01013
01014
01015
01016 StoreLightMatrices();
01017
01018
01019 glViewport(0, 0, (int)SHADOW_WIDTH, (int)SHADOW_HEIGHT);
01020
01021
01022 glClearColor(0.0f,0.0f,0.0f,0.0f);
01023 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01024
01025
01026 glMatrixMode(GL_PROJECTION);
01027
01028
01029 glPushMatrix();{
01030
01031 glLoadMatrixf(g_mProjection);
01032
01033
01034 glMatrixMode(GL_MODELVIEW);
01035 glPushMatrix();{
01036
01037 glLoadMatrixf(g_mModelView);
01038
01039
01040
01041 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
01042
01043
01044
01045 glEnable(GL_POLYGON_OFFSET_FILL);
01046 glDisable(GL_BLEND);
01047
01048
01049
01050 glPolygonOffset(g_DepthOffset[0], g_DepthOffset[1]);
01051
01052 _sceneTransform.Apply();
01053
01054 DisplayOBJs(true);
01055
01056
01057 glDisable(GL_BLEND);
01058
01059 glBindTexture(GL_TEXTURE_2D, g_DepthTexture);
01060
01061 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, (int)SHADOW_WIDTH, (int)SHADOW_HEIGHT);
01062
01063
01064 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
01065
01066
01067 glDisable(GL_POLYGON_OFFSET_FILL);
01068
01069 }glPopMatrix();
01070
01071 glMatrixMode(GL_PROJECTION);
01072
01073 }glPopMatrix();
01074
01075
01076 glMatrixMode(GL_MODELVIEW);
01077
01078
01079 glViewport(0, 0, GetWidth(), GetHeight());
01080
01081
01082 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01083
01084
01085
01086
01087
01088
01089
01090 glLightfv( GL_LIGHT0, GL_POSITION, _lightPosition );
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128 glMatrixMode(GL_PROJECTION);
01129 glLoadMatrixd(lastProjectionMatrix);
01130 glMatrixMode(GL_MODELVIEW);
01131 ApplyShadowMap();
01132 {
01133 Enable<GL_TEXTURE_2D> texture_on;
01134 glDisable(GL_BLEND);
01135 glBindTexture(GL_TEXTURE_2D, ShadowTextureMask);
01136 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GetWidth(), GetHeight());
01137 }
01138 if (_background==0)
01139 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
01140 else if (_background==1)
01141 glClearColor(0.0f,0.0f,0.0f,0.0f);
01142 else if (_background==2)
01143 glClearColor(1.0f,1.0f,1.0f,1.0f);
01144 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01145 if (_background==0)
01146 DrawLogo();
01147
01148 _sceneTransform.Apply();
01149 DisplayOBJs();
01150
01151
01152 {
01153 float ofu = GetWidth()/(float)SHADOW_MASK_SIZE;
01154 float ofv = GetHeight()/(float)SHADOW_MASK_SIZE;
01155 glActiveTextureARB(GL_TEXTURE0_ARB);
01156 glEnable(GL_TEXTURE_2D);
01157 glBindTexture(GL_TEXTURE_2D,ShadowTextureMask);
01158
01159 Disable<GL_DEPTH_TEST> dtoff;
01160 Disable<GL_LIGHTING> dlight;
01161 Enable<GL_BLEND> blend_on;
01162 glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
01163 glColor3f(1,1,1);
01164 glViewport(0, 0, GetWidth(), GetHeight());
01165 glMatrixMode(GL_PROJECTION);
01166 glPushMatrix();
01167 glLoadIdentity();
01168 glOrtho(0,1,0,1,-1,1);
01169 glMatrixMode(GL_MODELVIEW);
01170 glPushMatrix();{
01171 glLoadIdentity();
01172 glBegin(GL_QUADS);{
01173 glTexCoord2f(0,0);
01174 glVertex2f(0,0);
01175 glTexCoord2f(0,ofv);
01176 glVertex2f(0,1);
01177 glTexCoord2f(ofu,ofv);
01178 glVertex2f(1,1);
01179 glTexCoord2f(ofu,0);
01180 glVertex2f(1,0);
01181 }glEnd();
01182 }glPopMatrix();
01183 glMatrixMode(GL_PROJECTION);
01184 glPopMatrix();
01185 glMatrixMode(GL_MODELVIEW);
01186 glViewport(0, 0, GetWidth(), GetHeight());
01187 glDisable(GL_TEXTURE_2D);
01188 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01189 }
01190
01191 }
01192 else
01193 #endif
01194 {
01195 if (_background==0)
01196 DrawLogo();
01197
01198 glLoadIdentity();
01199 _sceneTransform.Apply();
01200
01201 glGetDoublev(GL_MODELVIEW_MATRIX,lastModelviewMatrix);
01202
01203 if (_renderingMode == GL_RENDER)
01204 {
01205
01206 glPushMatrix();
01207 glLoadIdentity();
01208 glLightfv(GL_LIGHT0, GL_POSITION, _lightPosition);
01209 glPopMatrix();
01210 Enable<GL_LIGHT0> light0;
01211
01212 glColor3f(0.5f, 0.5f, 0.6f);
01213
01214
01215
01216 DisplayOBJs();
01217
01218 DisplayMenu();
01219 }
01220 }
01221 }
01222
01223
01224
01225
01226
01227
01228 void QtViewer::resizeGL(int width, int height)
01229 {
01230
01231 _W = width;
01232 _H = height;
01233
01234
01235
01236 calcProjection();
01237 this->resize(width, height);
01238 emit( resizeW( _W ) );
01239 emit( resizeH( _H ) );
01240 }
01241
01242
01243
01244
01245
01246 void QtViewer::calcProjection()
01247 {
01248 int width = _W;
01249 int height = _H;
01250 double xNear, yNear, zNear, zFar, xOrtho, yOrtho;
01251 double xFactor = 1.0, yFactor = 1.0;
01252 double offset;
01253 double xForeground, yForeground, zForeground, xBackground, yBackground,
01254 zBackground;
01255 Vector3 center;
01256
01257
01258 if (groot && (!sceneBBoxIsValid || _axis))
01259 {
01260 getSimulation()->computeBBox(groot, sceneMinBBox.ptr(), sceneMaxBBox.ptr());
01261 sceneBBoxIsValid = true;
01262 }
01263 if (sceneMaxBBox==Vector3() && sceneMinBBox==Vector3())_zoomSpeed = _panSpeed = 2;
01264
01265 if (!sceneBBoxIsValid || sceneMinBBox[0] > sceneMaxBBox[0])
01266 {
01267 zNear = 1.0;
01268 zFar = 1000.0;
01269 }
01270 else
01271 {
01272 zNear = 1e10;
01273 zFar = -1e10;
01274 double minBBox[3] = {sceneMinBBox[0], sceneMinBBox[1], sceneMinBBox[2] };
01275 double maxBBox[3] = {sceneMaxBBox[0], sceneMaxBBox[1], sceneMaxBBox[2] };
01276 center = (sceneMinBBox+sceneMaxBBox)*0.5;
01277 if (_axis)
01278 {
01279 for (int i=0;i<3;i++)
01280 {
01281 if (minBBox[i]>-2) minBBox[i] = -2;
01282 if (maxBBox[i]<14) maxBBox[i] = 14;
01283 }
01284 }
01285
01286 for (int corner=0;corner<8;++corner)
01287 {
01288 Vector3 p((corner&1)?minBBox[0]:maxBBox[0],
01289 (corner&2)?minBBox[1]:maxBBox[1],
01290 (corner&4)?minBBox[2]:maxBBox[2]);
01291 p = _sceneTransform * p;
01292 double z = -p[2];
01293 if (z < zNear) zNear = z;
01294 if (z > zFar) zFar = z;
01295 }
01296 if (zFar <= 0 || zFar >= 1000)
01297 {
01298 zNear = 1;
01299 zFar = 1000.0;
01300 }
01301 else
01302 {
01303 zNear *= 0.9;
01304 zFar *= 1.1;
01305 if (zNear < zFar*0.01)
01306 zNear = zFar*0.01;
01307 if (zNear < 0.1) zNear = 0.1;
01308 if (zFar < 2.0) zFar = 2.0;
01309 }
01310
01311 }
01312 xNear = 0.35*zNear;
01313 yNear = 0.35*zNear;
01314 offset = 0.001*zNear;
01315
01316 xOrtho = fabs(_sceneTransform.translation[2]) * xNear / zNear;
01317 yOrtho = fabs(_sceneTransform.translation[2]) * yNear / zNear;
01318
01319 if ((height != 0) && (width != 0))
01320 {
01321 if (height > width)
01322 {
01323 xFactor = 1.0;
01324 yFactor = (double) height / (double) width;
01325 }
01326 else
01327 {
01328 xFactor = (double) width / (double) height;
01329 yFactor = 1.0;
01330 }
01331 }
01332
01333 lastViewport[0] = 0;
01334 lastViewport[1] = 0;
01335 lastViewport[2] = width;
01336 lastViewport[3] = height;
01337 glViewport(0, 0, width, height);
01338 glMatrixMode(GL_PROJECTION);
01339 glLoadIdentity();
01340
01341 xFactor *= 0.01;
01342 yFactor *= 0.01;
01343 zNear *= 0.01;
01344 zFar *= 10.0;
01345
01346 zForeground = -zNear - offset;
01347 zBackground = -zFar + offset;
01348
01349 if (camera_type == CAMERA_PERSPECTIVE)
01350 glFrustum(-xNear * xFactor, xNear * xFactor, -yNear * yFactor,
01351 yNear * yFactor, zNear, zFar);
01352 else
01353 {
01354 float ratio = zFar/(zNear*20);
01355
01356 Vector3 tcenter = _sceneTransform * center;
01357
01358
01359
01360 std::cout << "center="<<center<<std::endl;
01361 std::cout << "tcenter="<<tcenter<<std::endl;
01362 if (tcenter[2] < 0.0)
01363 {
01364 ratio = -300*(tcenter.norm2())/tcenter[2];
01365 std::cout << "ratio="<<ratio<<std::endl;
01366 }
01367 glOrtho( (-xNear * xFactor)*ratio , (xNear * xFactor)*ratio , (-yNear * yFactor)*ratio,
01368 (yNear * yFactor)*ratio, zNear, zFar);
01369 }
01370
01371 xForeground = -zForeground * xNear / zNear;
01372 yForeground = -zForeground * yNear / zNear;
01373 xBackground = -zBackground * xNear / zNear;
01374 yBackground = -zBackground * yNear / zNear;
01375
01376 xForeground *= xFactor;
01377 yForeground *= yFactor;
01378 xBackground *= xFactor;
01379 yBackground *= yFactor;
01380
01381 glGetDoublev(GL_PROJECTION_MATRIX,lastProjectionMatrix);
01382
01383 glMatrixMode(GL_MODELVIEW);
01384 }
01385
01386
01387
01388
01389 void QtViewer::paintGL()
01390 {
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410 if (_background==0)
01411 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
01412 else if (_background==1)
01413 glClearColor(0.0f,0.0f,0.0f,0.0f);
01414 else if (_background==2)
01415 glClearColor(1.0f,1.0f,1.0f,1.0f);
01416 glClearDepth(1.0);
01417 glClear(_clearBuffer);
01418
01419
01420 DrawScene();
01421
01422 if (_video)
01423 {
01424 #ifdef CAPTURE_PERIOD
01425 static int counter = 0;
01426 if ((counter++ % CAPTURE_PERIOD)==0)
01427 #endif
01428 screenshot(capture.findFilename(), 1);
01429 }
01430
01431 if (_waitForRender)
01432 _waitForRender = false;
01433
01434 emit( redrawn() );
01435 }
01436
01437
01438
01439
01440 void QtViewer::ApplySceneTransformation(int x, int y)
01441 {
01442 float x1, x2, y1, y2;
01443 float xshift, yshift, zshift;
01444
01445 if (_moving)
01446 {
01447 if (_navigationMode == TRACKBALL_MODE)
01448 {
01449 x1 = (2.0f * _W / 2.0f - _W) / _W;
01450 y1 = (_H - 2.0f * _H / 2.0f) / _H;
01451 x2 = (2.0f * (x + (-_mouseX + _W / 2.0f)) - _W) / _W;
01452 y2 = (_H - 2.0f * (y + (-_mouseY + _H / 2.0f))) / _H;
01453 _currentTrackball.ComputeQuaternion(x1, y1, x2, y2);
01454 _currentQuat = _currentTrackball.GetQuaternion();
01455 _savedMouseX = _mouseX;
01456 _savedMouseY = _mouseY;
01457 _mouseX = x;
01458 _mouseY = y;
01459 _newQuat = _currentQuat + _newQuat;
01460 update();
01461 }
01462 else if (_navigationMode == ZOOM_MODE)
01463 {
01464 zshift = (2.0f * y - _W) / _W - (2.0f * _mouseY - _W) / _W;
01465 _sceneTransform.translation[2] = _previousEyePos[2] +
01466 _zoomSpeed * zshift;
01467 update();
01468 }
01469 else if (_navigationMode == PAN_MODE)
01470 {
01471 xshift = (2.0f * x - _W) / _W - (2.0f * _mouseX - _W) / _W;
01472 yshift = (2.0f * y - _W) / _W - (2.0f * _mouseY - _W) / _W;
01473 _sceneTransform.translation[0] = _previousEyePos[0] +
01474 _panSpeed * xshift;
01475 _sceneTransform.translation[1] = _previousEyePos[1] -
01476 _panSpeed * yshift;
01477 update();
01478 }
01479 }
01480 }
01481
01482
01483
01484
01485
01486 void QtViewer::ApplyMouseInteractorTransformation(int x, int y)
01487 {
01488
01489 double coeffDeplacement = 0.025;
01490 if (sceneBBoxIsValid)
01491 coeffDeplacement *= 0.001*(sceneMaxBBox-sceneMinBBox).norm();
01492 Quaternion conjQuat, resQuat, _newQuatBckUp;
01493
01494 float x1, x2, y1, y2;
01495
01496 if (_mouseInteractorMoving)
01497 {
01498 if (_mouseInteractorRotationMode)
01499 {
01500 if ((_mouseInteractorSavedPosX != x) || (_mouseInteractorSavedPosY != y))
01501 {
01502 x1 = 0;
01503 y1 = 0;
01504 x2 = (2.0f * (x + (-_mouseInteractorSavedPosX + _W / 2.0f)) - _W) / _W;
01505 y2 = (_H - 2.0f * (y + (-_mouseInteractorSavedPosY + _H / 2.0f))) / _H;
01506
01507 _mouseInteractorTrackball.ComputeQuaternion(x1, y1, x2, y2);
01508 _mouseInteractorCurrentQuat = _mouseInteractorTrackball.GetQuaternion();
01509 _mouseInteractorSavedPosX = x;
01510 _mouseInteractorSavedPosY = y;
01511
01512 _mouseInteractorNewQuat = _mouseInteractorCurrentQuat + _mouseInteractorNewQuat;
01513 _mouseRotate = true;
01514 }
01515 else
01516 {
01517 _mouseRotate = false;
01518 }
01519
01520 update();
01521 }
01522 else if (_mouseInteractorTranslationMode)
01523 {
01524 _mouseInteractorAbsolutePosition = Vector3(0,0,0);
01525 _mouseInteractorRelativePosition = Vector3(0,0,0);
01526
01527 if (_translationMode == XY_TRANSLATION)
01528 {
01529 _mouseInteractorAbsolutePosition[0] = coeffDeplacement * (x - _mouseInteractorSavedPosX);
01530 _mouseInteractorAbsolutePosition[1] = -coeffDeplacement * (y - _mouseInteractorSavedPosY);
01531
01532 _mouseInteractorSavedPosX = x;
01533 _mouseInteractorSavedPosY = y;
01534 }
01535 else if (_translationMode == Z_TRANSLATION)
01536 {
01537 _mouseInteractorAbsolutePosition[2] = coeffDeplacement * (y - _mouseInteractorSavedPosY);
01538
01539 _mouseInteractorSavedPosX = x;
01540 _mouseInteractorSavedPosY = y;
01541 }
01542
01543 _newQuatBckUp[0] = _newQuat[0];
01544 _newQuatBckUp[1] = _newQuat[1];
01545 _newQuatBckUp[2] = _newQuat[2];
01546 _newQuatBckUp[3] = _newQuat[3];
01547
01548 _newQuatBckUp.normalize();
01549
01550
01551 conjQuat[0] = -_newQuatBckUp[0];
01552 conjQuat[1] = -_newQuatBckUp[1];
01553 conjQuat[2] = -_newQuatBckUp[2];
01554 conjQuat[3] = _newQuatBckUp[3];
01555
01556 conjQuat.normalize();
01557
01558 resQuat = _newQuatBckUp.quatVectMult(_mouseInteractorAbsolutePosition) * conjQuat;
01559
01560 _mouseInteractorRelativePosition[0] = resQuat[0];
01561 _mouseInteractorRelativePosition[1] = resQuat[1];
01562 _mouseInteractorRelativePosition[2] = resQuat[2];
01563
01564 _mouseTrans = true;
01565 update();
01566 }
01567 }
01568 }
01569
01570
01571
01572
01573
01574
01575
01576 void QtViewer::keyPressEvent ( QKeyEvent * e )
01577 {
01578 if( isControlPressed() )
01579 {
01580
01581 if (groot)
01582 {
01583 sofa::core::objectmodel::KeypressedEvent keyEvent(e->key());
01584 groot->propagateEvent(&keyEvent);
01585 }
01586 }
01587 else
01588 switch(e->key())
01589 {
01590
01591
01592 case Qt::Key_C:
01593 {
01594
01595 if (!_mouseInteractorTranslationMode)
01596 {
01597 std::cout << "Interaction Mode ON\n";
01598 _mouseInteractorTranslationMode = true;
01599 _mouseInteractorRotationMode = false;
01600 }
01601 else
01602 {
01603 std::cout << "Interaction Mode OFF\n";
01604 _mouseInteractorTranslationMode = false;
01605 _mouseInteractorRotationMode = false;
01606 }
01607 break;
01608 }
01609 default:
01610 {
01611 SofaViewer::keyPressEvent(e);
01612 e->ignore();
01613 }
01614 update();
01615 }
01616 }
01617
01618 void QtViewer::keyReleaseEvent ( QKeyEvent * e )
01619 {
01620 SofaViewer::keyReleaseEvent(e);
01621 }
01622
01623
01624 void QtViewer::wheelEvent(QWheelEvent* e)
01625 {
01626 if( e->state()&Qt::ControlButton )
01627 {
01628 moveLaparoscopic(e);
01629 }
01630 else
01631 {
01632 int eventX = e->x();
01633 int eventY = e->y();
01634
01635 _navigationMode = ZOOM_MODE;
01636 _moving = true;
01637 _spinning = false;
01638 _mouseX = eventX;
01639 _mouseY = eventY + e->delta();
01640 _previousEyePos[2] = _sceneTransform.translation[2];
01641 ApplySceneTransformation(eventX, eventY);
01642
01643 _moving = false;
01644 }
01645 }
01646
01647 void QtViewer::mousePressEvent ( QMouseEvent * e )
01648 {
01649 mouseEvent(e);
01650 }
01651
01652 void QtViewer::mouseReleaseEvent ( QMouseEvent * e )
01653 {
01654 mouseEvent(e);
01655 }
01656
01657 void QtViewer::mouseMoveEvent ( QMouseEvent * e )
01658 {
01659 mouseEvent(e);
01660 }
01661
01662
01663
01664 void QtViewer::mouseEvent ( QMouseEvent * e )
01665 {
01666 int eventX = e->x();
01667 int eventY = e->y();
01668 if (_mouseInteractorRotationMode)
01669 {
01670 switch (e->type())
01671 {
01672 case QEvent::MouseButtonPress:
01673
01674 if (e->button() == Qt::LeftButton)
01675 {
01676 _mouseInteractorMoving = true;
01677 _mouseInteractorSavedPosX = eventX;
01678 _mouseInteractorSavedPosY = eventY;
01679 }
01680 break;
01681
01682 case QEvent::MouseMove:
01683
01684 break;
01685
01686 case QEvent::MouseButtonRelease:
01687
01688 if (e->button() == Qt::LeftButton)
01689 {
01690 if (_mouseInteractorMoving)
01691 {
01692 _mouseInteractorMoving = false;
01693 }
01694 }
01695 break;
01696
01697 default:
01698 break;
01699 }
01700 ApplyMouseInteractorTransformation(eventX, eventY);
01701 }
01702 else if (_mouseInteractorTranslationMode)
01703 {
01704 switch (e->type())
01705 {
01706 case QEvent::MouseButtonPress:
01707
01708 if (e->button() == Qt::LeftButton)
01709 {
01710 _translationMode = XY_TRANSLATION;
01711 _mouseInteractorSavedPosX = eventX;
01712 _mouseInteractorSavedPosY = eventY;
01713 _mouseInteractorMoving = true;
01714 }
01715
01716 else if (e->button() == Qt::RightButton)
01717 {
01718 _translationMode = Z_TRANSLATION;
01719 _mouseInteractorSavedPosY = eventY;
01720 _mouseInteractorMoving = true;
01721 }
01722
01723 break;
01724
01725 case QEvent::MouseButtonRelease:
01726
01727 if ((e->button() == Qt::LeftButton) && (_translationMode == XY_TRANSLATION))
01728 {
01729 _mouseInteractorMoving = false;
01730 }
01731
01732 else if ((e->button() == Qt::RightButton) && (_translationMode == Z_TRANSLATION))
01733 {
01734 _mouseInteractorMoving = false;
01735 }
01736 break;
01737
01738
01739 default:
01740 break;
01741 }
01742
01743 ApplyMouseInteractorTransformation(eventX, eventY);
01744 }
01745 else if (e->state()&Qt::ShiftButton)
01746 {
01747 _moving = false;
01748 SofaViewer::mouseEvent(e);
01749 }
01750 else if (e->state()&Qt::ControlButton)
01751 {
01752 moveLaparoscopic(e);
01753 }
01754 else if (e->state()&Qt::AltButton)
01755 {
01756 _moving = false;
01757 switch (e->type())
01758 {
01759 case QEvent::MouseButtonPress:
01760
01761 if (e->button() == Qt::LeftButton)
01762 {
01763 _navigationMode = BTLEFT_MODE;
01764 _mouseInteractorMoving = true;
01765 _mouseInteractorSavedPosX = eventX;
01766 _mouseInteractorSavedPosY = eventY;
01767 }
01768
01769 else if (e->button() == Qt::RightButton)
01770 {
01771 _navigationMode = BTRIGHT_MODE;
01772 _mouseInteractorMoving = true;
01773 _mouseInteractorSavedPosX = eventX;
01774 _mouseInteractorSavedPosY = eventY;
01775 }
01776
01777 else if (e->button() == Qt::MidButton)
01778 {
01779 _navigationMode = BTMIDDLE_MODE;
01780 _mouseInteractorMoving = true;
01781 _mouseInteractorSavedPosX = eventX;
01782 _mouseInteractorSavedPosY = eventY;
01783 }
01784 break;
01785
01786 case QEvent::MouseMove:
01787
01788 break;
01789
01790 case QEvent::MouseButtonRelease:
01791
01792 if (e->button() == Qt::LeftButton)
01793 {
01794 if (_mouseInteractorMoving)
01795 {
01796 _mouseInteractorMoving = false;
01797 }
01798 }
01799
01800 else if (e->button() == Qt::RightButton)
01801 {
01802 if (_mouseInteractorMoving)
01803 {
01804 _mouseInteractorMoving = false;
01805 }
01806 }
01807
01808 else if (e->button() == Qt::MidButton)
01809 {
01810 if (_mouseInteractorMoving)
01811 {
01812 _mouseInteractorMoving = false;
01813 }
01814 }
01815 break;
01816
01817 default:
01818 break;
01819 }
01820 if (_mouseInteractorMoving && _navigationMode == BTLEFT_MODE)
01821 {
01822 int dx = eventX - _mouseInteractorSavedPosX;
01823 int dy = eventY - _mouseInteractorSavedPosY;
01824 if (dx || dy)
01825 {
01826 _lightPosition[0] -= dx*0.1;
01827 _lightPosition[1] += dy*0.1;
01828 std::cout << "Light = "<< _lightPosition[0] << " "<< _lightPosition[1] << " "<< _lightPosition[2] << std::endl;
01829 update();
01830 _mouseInteractorSavedPosX = eventX;
01831 _mouseInteractorSavedPosY = eventY;
01832 }
01833 }
01834 else if (_mouseInteractorMoving && _navigationMode == BTRIGHT_MODE)
01835 {
01836 int dx = eventX - _mouseInteractorSavedPosX;
01837 int dy = eventY - _mouseInteractorSavedPosY;
01838 if (dx || dy)
01839 {
01840
01841 g_DepthBias[1] += dy*0.01;
01842 std::cout << "Depth bias = "<< g_DepthBias[0] << " " << g_DepthBias[1] << std::endl;
01843 update();
01844 _mouseInteractorSavedPosX = eventX;
01845 _mouseInteractorSavedPosY = eventY;
01846 }
01847 }
01848 else if (_mouseInteractorMoving && _navigationMode == BTMIDDLE_MODE)
01849 {
01850
01851 int dx = eventX - _mouseInteractorSavedPosX;
01852 int dy = eventY - _mouseInteractorSavedPosY;
01853 if (dx || dy)
01854 {
01855 g_DepthOffset[0] += dx*0.01;
01856 g_DepthOffset[1] += dy*0.01;
01857 std::cout << "Depth offset = "<< g_DepthOffset[0] << " " << g_DepthOffset[1] << std::endl;
01858 update();
01859 _mouseInteractorSavedPosX = eventX;
01860 _mouseInteractorSavedPosY = eventY;
01861 }
01862 }
01863 }
01864 else
01865 {
01866 if (interactor!=NULL)
01867 interactor->newEvent("hide");
01868 switch (e->type())
01869 {
01870 case QEvent::MouseButtonPress:
01871
01872 if (e->button() == Qt::LeftButton)
01873 {
01874 _navigationMode = TRACKBALL_MODE;
01875 _newTrackball.ComputeQuaternion(0.0, 0.0, 0.0, 0.0);
01876 _currentQuat = _newTrackball.GetQuaternion();
01877 _moving = true;
01878 _spinning = false;
01879 timerAnimate->stop();
01880 _mouseX = eventX;
01881 _mouseY = eventY;
01882 }
01883
01884 else if (e->button() == Qt::RightButton)
01885 {
01886 _navigationMode = PAN_MODE;
01887 _moving = true;
01888 _spinning = false;
01889 _mouseX = eventX;
01890 _mouseY = eventY;
01891 _previousEyePos[0] = _sceneTransform.translation[0];
01892 _previousEyePos[1] = _sceneTransform.translation[1];
01893 }
01894
01895 else if (e->button() == Qt::MidButton)
01896 {
01897 _navigationMode = ZOOM_MODE;
01898 _moving = true;
01899 _spinning = false;
01900 _mouseX = eventX;
01901 _mouseY = eventY;
01902 _previousEyePos[2] = _sceneTransform.translation[2];
01903 }
01904 break;
01905
01906 case QEvent::MouseMove:
01907
01908 break;
01909
01910 case QEvent::MouseButtonRelease:
01911
01912 if (e->button() == Qt::LeftButton)
01913 {
01914 if (_moving && _navigationMode == TRACKBALL_MODE)
01915 {
01916 _moving = false;
01917 int dx = eventX - _savedMouseX;
01918 int dy = eventY - _savedMouseY;
01919 if ((dx >= MINMOVE) || (dx <= -MINMOVE) ||
01920 (dy >= MINMOVE) || (dy <= -MINMOVE))
01921 {
01922 _spinning = true;
01923 timerAnimate->start(10);
01924 }
01925 }
01926 }
01927
01928 else if (e->button() == Qt::RightButton)
01929 {
01930 if (_moving && _navigationMode == PAN_MODE)
01931 {
01932 _moving = false;
01933 }
01934 }
01935
01936 else if (e->button() == Qt::MidButton)
01937 {
01938 if (_moving && _navigationMode == ZOOM_MODE)
01939 {
01940 _moving = false;
01941 }
01942 }
01943
01944 break;
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961 default:
01962 break;
01963 }
01964
01965 ApplySceneTransformation(eventX, eventY);
01966 }
01967 }
01968
01969 void QtViewer::moveRayPickInteractor(int eventX, int eventY)
01970 {
01971
01972 Vec3d p0, px, py, pz;
01973 gluUnProject(eventX, lastViewport[3]-1-(eventY), 0, lastModelviewMatrix, lastProjectionMatrix, lastViewport, &(p0[0]), &(p0[1]), &(p0[2]));
01974 gluUnProject(eventX+1, lastViewport[3]-1-(eventY), 0, lastModelviewMatrix, lastProjectionMatrix, lastViewport, &(px[0]), &(px[1]), &(px[2]));
01975 gluUnProject(eventX, lastViewport[3]-1-(eventY+1), 0, lastModelviewMatrix, lastProjectionMatrix, lastViewport, &(py[0]), &(py[1]), &(py[2]));
01976 gluUnProject(eventX, lastViewport[3]-1-(eventY), 0.1, lastModelviewMatrix, lastProjectionMatrix, lastViewport, &(pz[0]), &(pz[1]), &(pz[2]));
01977 px -= p0;
01978 py -= p0;
01979 pz -= p0;
01980 px.normalize();
01981 py.normalize();
01982 pz.normalize();
01983 Mat4x4d transform;
01984 transform.identity();
01985 transform[0][0] = px[0];
01986 transform[1][0] = px[1];
01987 transform[2][0] = px[2];
01988 transform[0][1] = py[0];
01989 transform[1][1] = py[1];
01990 transform[2][1] = py[2];
01991 transform[0][2] = pz[0];
01992 transform[1][2] = pz[1];
01993 transform[2][2] = pz[2];
01994 transform[0][3] = p0[0];
01995 transform[1][3] = p0[1];
01996 transform[2][3] = p0[2];
01997 Mat3x3d mat; mat = transform;
01998 Quat q; q.fromMatrix(mat);
01999
02000 interactor->newPosition(p0, q, transform);
02001 }
02002
02003
02004
02005
02006 void QtViewer::resetView()
02007 {
02008 if (!sceneFileName.empty())
02009 {
02010 std::string viewFileName = sceneFileName+".view";
02011 std::ifstream in(viewFileName.c_str());
02012 if (!in.fail())
02013 {
02014 in >> _sceneTransform.translation[0];
02015 in >> _sceneTransform.translation[1];
02016 in >> _sceneTransform.translation[2];
02017 in >> _newQuat[0];
02018 in >> _newQuat[1];
02019 in >> _newQuat[2];
02020 in >> _newQuat[3];
02021 _newQuat.normalize();
02022 in.close();
02023 update();
02024 return;
02025 }
02026 }
02027 _sceneTransform.translation[0] = 0.0;
02028 _sceneTransform.translation[1] = 0.0;
02029 if (sceneBBoxIsValid)
02030 _sceneTransform.translation[2] = -(sceneMaxBBox-sceneMinBBox).norm();
02031 else
02032 _sceneTransform.translation[2] = -50.0;
02033 _newQuat[0] = 0.17;
02034 _newQuat[1] = -0.83;
02035 _newQuat[2] = -0.26;
02036 _newQuat[3] = -0.44;
02037 update();
02038
02039 }
02040
02041
02042 void QtViewer::saveView()
02043 {
02044 if (!sceneFileName.empty())
02045 {
02046 std::string viewFileName = sceneFileName+".view";
02047 std::ofstream out(viewFileName.c_str());
02048 if (!out.fail())
02049 {
02050 out << _sceneTransform.translation[0] << " " << _sceneTransform.translation[1] << " " << _sceneTransform.translation[2] << "\n";
02051 out << _newQuat[0] << " " << _newQuat[1] << " " << _newQuat[2] << " " << _newQuat[3] << "\n";
02052 out.close();
02053 }
02054 std::cout << "View parameters saved in "<<viewFileName<<std::endl;
02055 }
02056 }
02057
02058
02059
02060 void QtViewer::setScene(sofa::simulation::tree::GNode* scene, const char* filename, bool keepParams)
02061 {
02062
02063 bool newScene = (scene != groot);
02064 SofaViewer::setScene(scene, filename, keepParams);
02065 if (newScene)
02066 {
02067 getSimulation()->computeBBox(groot, sceneMinBBox.ptr(), sceneMaxBBox.ptr());
02068 _panSpeed = (sceneMaxBBox-sceneMinBBox).norm()*0.5;
02069 _zoomSpeed = (sceneMaxBBox-sceneMinBBox).norm();
02070 }
02071 }
02072
02073
02074 void QtViewer::setSizeW( int size )
02075 {
02076 resizeGL( size, _H );
02077 updateGL();
02078 }
02079
02080 void QtViewer::setSizeH( int size )
02081 {
02082 resizeGL( _W, size );
02083 updateGL();
02084 }
02085
02086
02087 QString QtViewer::helpString()
02088 {
02089 QString text(
02090 "<H1>QtViewer</H1><hr>\
02091 <ul>\
02092 <li><b>Mouse</b>: TO NAVIGATE<br></li>\
02093 <li><b>Shift & Left Button</b>: TO PICK OBJECTS<br></li>\
02094 <li><b>B</b>: TO CHANGE THE BACKGROUND<br></li>\
02095 <li><b>C</b>: TO SWITCH INTERACTION MODE: press the KEY C.<br>\
02096 Allow or not the navigation with the mouse.<br></li>\
02097 <li><b>L</b>: TO DRAW SHADOWS<br></li>\
02098 <li><b>O</b>: TO EXPORT TO .OBJ<br>\
02099 The generated files scene-time.obj and scene-time.mtl are saved in the running project directory<br></li>\
02100 <li><b>P</b>: TO SAVE A SEQUENCE OF OBJ<br>\
02101 Each time the frame is updated an obj is exported<br></li>\
02102 <li><b>R</b>: TO DRAW THE SCENE AXIS<br></li>\
02103 <li><b>S</b>: TO SAVE A SCREENSHOT<br>\
02104 The captured images are saved in the running project directory under the name format capturexxxx.bmp<br></li>\
02105 <li><b>T</b>: TO CHANGE BETWEEN A PERSPECTIVE OR AN ORTHOGRAPHIC CAMERA<br></li>\
02106 <li><b>V</b>: TO SAVE A VIDEO<br>\
02107 Each time the frame is updated a screenshot is saved<br></li>\
02108 <li><b>Esc</b>: TO QUIT ::sofa:: <br></li></ul>");
02109 return text;
02110 }
02111
02112 }
02113
02114 }
02115
02116 }
02117
02118 }
02119
02120 }