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/qgl/QtGLViewer.h"
00028 #include <sofa/helper/system/config.h>
00029 #include <sofa/helper/system/FileRepository.h>
00030 #include <sofa/helper/system/thread/CTime.h>
00031 #include <sofa/simulation/tree/Simulation.h>
00032 #include <sofa/simulation/common/MechanicalVisitor.h>
00033 #include <sofa/simulation/common/UpdateMappingVisitor.h>
00034 #include <sofa/core/objectmodel/KeypressedEvent.h>
00035 #include <sofa/core/objectmodel/KeyreleasedEvent.h>
00036 #include <sofa/core/ObjectFactory.h>
00037
00038 #include <math.h>
00039 #include <iostream>
00040 #include <fstream>
00041 #include <string.h>
00042 #include <math.h>
00043 #include <sofa/helper/system/gl.h>
00044 #include <sofa/helper/system/glu.h>
00045 #include <sofa/helper/system/glut.h>
00046 #include <qevent.h>
00047 #include "GenGraphForm.h"
00048 #include "Main.h"
00049
00050 #include <sofa/helper/gl/glfont.h>
00051 #include <sofa/helper/gl/RAII.h>
00052 #ifdef SOFA_HAVE_GLEW
00053 #include <sofa/helper/gl/GLSLShader.h>
00054 #endif
00055 #include <sofa/helper/io/ImageBMP.h>
00056
00057
00058 #include <sofa/defaulttype/RigidTypes.h>
00059
00060
00061
00062
00063
00064
00065 namespace sofa
00066 {
00067
00068 namespace gui
00069 {
00070
00071 namespace qt
00072 {
00073
00074 namespace viewer
00075 {
00076
00077 namespace qgl
00078 {
00079
00080 using std::cout;
00081 using std::endl;
00082 using namespace sofa::defaulttype;
00083 using namespace sofa::helper::gl;
00084 using sofa::simulation::tree::getSimulation;
00085
00086
00087
00088
00089
00090
00091 #ifdef SOFA_HAVE_GLEW
00092
00093
00094
00095 enum { SHADOW_WIDTH = 512 };
00096 enum { SHADOW_HEIGHT = 512 };
00097 enum { SHADOW_MASK_SIZE = 2048 };
00098
00099
00100
00101 #define GL_TEXTURE_COMPARE_MODE_ARB 0x884C
00102
00103
00104
00105 #define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D
00106
00107
00108 #define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E
00109
00110
00111 GLuint g_DepthTexture;
00112
00113
00114 GLSLShader g_Shader;
00115
00116
00117 float g_DepthOffset[2] = { 10.0f, 0.0f };
00118 float g_DepthBias[2] = { 0.0f, 0.0f };
00119
00120
00121 float g_mProjection[16] = {0};
00122 float g_mModelView[16] = {0};
00123
00124
00125 GLuint ShadowTextureMask;
00126
00127
00128 #endif // SOFA_HAVE_GLEW
00129
00130 static bool enabled = false;
00131 sofa::core::ObjectFactory::ClassEntry* classVisualModel;
00132
00136 int QtGLViewer::EnableViewer()
00137 {
00138 if (!enabled)
00139 {
00140 enabled = true;
00141
00142 sofa::core::ObjectFactory::AddAlias("VisualModel", "OglModel", true, &classVisualModel);
00143 }
00144 return 0;
00145 }
00146
00150 int QtGLViewer::DisableViewer()
00151 {
00152 if (enabled)
00153 {
00154 enabled = false;
00155 sofa::core::ObjectFactory::ResetAlias("VisualModel", classVisualModel);
00156 }
00157 return 0;
00158 }
00159
00160
00161
00162
00163 QtGLViewer::QtGLViewer(QWidget* parent, const char* name)
00164 : QGLViewer(parent, name)
00165 {
00166
00167 groot = NULL;
00168 initTexturesDone = false;
00169
00170
00171 timerAnimate = new QTimer(this);
00172 connect( timerAnimate, SIGNAL(timeout()), this, SLOT(animate()) );
00173
00174
00175
00176
00177
00178 _video = false;
00179 _axis = false;
00180 _background = 0;
00181 _shadow = false;
00182 _gl_shadow = false;
00183 _numOBJmodels = 0;
00184 _materialMode = 0;
00185 _facetNormal = GL_FALSE;
00186 _renderingMode = GL_RENDER;
00187
00188 sceneBBoxIsValid = false;
00189 texLogo = NULL;
00190
00191
00192
00193
00194
00195
00196
00197 _arrow = gluNewQuadric();
00198 gluQuadricDrawStyle(_arrow, GLU_FILL);
00199 gluQuadricOrientation(_arrow, GLU_OUTSIDE);
00200 gluQuadricNormals(_arrow, GLU_SMOOTH);
00201
00202 _tube = gluNewQuadric();
00203 gluQuadricDrawStyle(_tube, GLU_FILL);
00204 gluQuadricOrientation(_tube, GLU_OUTSIDE);
00205 gluQuadricNormals(_tube, GLU_SMOOTH);
00206
00207 _sphere = gluNewQuadric();
00208 gluQuadricDrawStyle(_sphere, GLU_FILL);
00209 gluQuadricOrientation(_sphere, GLU_OUTSIDE);
00210 gluQuadricNormals(_sphere, GLU_SMOOTH);
00211
00212 _disk = gluNewQuadric();
00213 gluQuadricDrawStyle(_disk, GLU_FILL);
00214 gluQuadricOrientation(_disk, GLU_OUTSIDE);
00215 gluQuadricNormals(_disk, GLU_SMOOTH);
00216
00217
00218
00220
00221
00222 interactor = NULL;
00223 _mouseInteractorMoving = false;
00224 _mouseInteractorSavedPosX = 0;
00225 _mouseInteractorSavedPosY = 0;
00226 m_isControlPressed = false;
00227
00228 setManipulatedFrame( new qglviewer::ManipulatedFrame() );
00229
00230 camera()->setZNearCoefficient(0.001);
00231 camera()->setZClippingCoefficient(5);
00232 }
00233
00234
00235
00236
00237
00238 QtGLViewer::~QtGLViewer()
00239 {
00240 }
00241
00242
00243
00244
00245
00246 void QtGLViewer::init(void)
00247 {
00248 restoreStateFromFile();
00249
00250
00251 static GLfloat specref[4];
00252 static GLfloat ambientLight[4];
00253 static GLfloat diffuseLight[4];
00254 static GLfloat specular[4];
00255 static GLfloat lmodel_ambient[] ={0.0f, 0.0f, 0.0f, 0.0f};
00256 static GLfloat lmodel_twoside[] ={GL_FALSE};
00257 static GLfloat lmodel_local[] ={GL_FALSE};
00258 bool initialized = false;
00259
00260 if (!initialized)
00261 {
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 _lightPosition[0] = -0.7f;
00272 _lightPosition[1] = 0.3f;
00273 _lightPosition[2] = 0.0f;
00274 _lightPosition[3] = 1.0f;
00275
00276 ambientLight[0] = 0.5f;
00277 ambientLight[1] = 0.5f;
00278 ambientLight[2] = 0.5f;
00279 ambientLight[3] = 1.0f;
00280
00281 diffuseLight[0] = 0.9f;
00282 diffuseLight[1] = 0.9f;
00283 diffuseLight[2] = 0.9f;
00284 diffuseLight[3] = 1.0f;
00285
00286 specular[0] = 1.0f;
00287 specular[1] = 1.0f;
00288 specular[2] = 1.0f;
00289 specular[3] = 1.0f;
00290
00291 specref[0] = 1.0f;
00292 specref[1] = 1.0f;
00293 specref[2] = 1.0f;
00294 specref[3] = 1.0f;
00295
00296
00297 #ifdef SOFA_HAVE_GLEW
00298 glewInit();
00299 if (!GLEW_ARB_multitexture)
00300 std::cerr << "Error: GL_ARB_multitexture not supported\n";
00301 #else
00302 glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) glewGetProcAddress("glActiveTextureARB");
00303 glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) glewGetProcAddress("glMultiTexCoord2fARB");
00304
00305
00306 if(!glActiveTextureARB || !glMultiTexCoord2fARB)
00307 {
00308
00309
00310
00311 }
00312 #endif
00313
00314 _clearBuffer = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
00315 _lightModelTwoSides = false;
00316
00317 glDepthFunc(GL_LEQUAL);
00318 glClearDepth(1.0);
00319 glEnable(GL_NORMALIZE);
00320
00321 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
00322
00323
00324 glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, lmodel_local);
00325 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
00326 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
00327
00328
00329 glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
00330 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
00331 glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
00332 glLightfv(GL_LIGHT0, GL_POSITION, _lightPosition);
00333
00334
00335 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
00336
00337
00338 glMaterialfv(GL_FRONT, GL_SPECULAR, specref);
00339 glMateriali(GL_FRONT, GL_SHININESS, 128);
00340
00341 glShadeModel(GL_SMOOTH);
00342
00343
00344 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
00345
00346
00347
00348 texLogo = new helper::gl::Texture(new helper::io::ImageBMP( sofa::helper::system::DataRepository.getFile("textures/SOFA_logo.bmp") ));
00349 texLogo->init();
00350
00351 glEnableClientState(GL_VERTEX_ARRAY);
00352
00353
00354
00355
00356 glEnable(GL_LIGHT0);
00357
00358
00359 #ifdef SOFA_HAVE_GLEW
00360
00361 CreateRenderTexture(g_DepthTexture, SHADOW_WIDTH, SHADOW_HEIGHT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT);
00362 CreateRenderTexture(ShadowTextureMask, SHADOW_MASK_SIZE, SHADOW_MASK_SIZE, GL_LUMINANCE, GL_LUMINANCE);
00363
00364 if ( GLSLShader::InitGLSL() )
00365 {
00366
00367 g_Shader.InitShaders(sofa::helper::system::DataRepository.getFile("shaders/ShadowMappingPCF.vert"), sofa::helper::system::DataRepository.getFile("shaders/ShadowMappingPCF.frag"));
00368 _gl_shadow = true;
00369 }
00370 else
00371 #endif
00372 {
00373 printf("WARNING QtGLViewer : shadows are not supported !\n");
00374 _gl_shadow=false;
00375 }
00376
00377
00378 initialized = true;
00379
00380 _beginTime = CTime::getTime();
00381
00382 printf("\n");
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 }
00398
00399
00400
00401 resetView();
00402
00403
00404
00405
00406 setShortcut(QGLViewer::SAVE_SCREENSHOT, Qt::Key_S);
00407 setShortcut(QGLViewer::HELP, Qt::Key_H);
00408 }
00409
00410
00411
00412
00413
00419
00420 void QtGLViewer::StoreLightMatrices()
00421 {
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 memset(g_mModelView, 0, sizeof(float)*16);
00432 memset(g_mProjection, 0, sizeof(float)*16);
00433
00434 g_mModelView[0] = 1;
00435 g_mModelView[5] = 1;
00436 g_mModelView[10] = 1;
00437 g_mModelView[15] = 1;
00438
00439
00440
00441
00442 float lx = -_lightPosition[0] * lastProjectionMatrix[0] - _lightPosition[1] * lastProjectionMatrix[4] + lastProjectionMatrix[12];
00443 float ly = -_lightPosition[0] * lastProjectionMatrix[1] - _lightPosition[1] * lastProjectionMatrix[5] + lastProjectionMatrix[13];
00444 float lz = -_lightPosition[0] * lastProjectionMatrix[2] - _lightPosition[1] * lastProjectionMatrix[6] + lastProjectionMatrix[14];
00445
00446
00447
00448 Vector3 l(-lx,-ly,-lz);
00449 Vector3 y;
00450 y = l.cross(Vector3(1,0,0));
00451 Vector3 x;
00452 x = y.cross(l);
00453 l.normalize();
00454 y.normalize();
00455 x.normalize();
00456
00457 g_mProjection[ 0] = x[0]; g_mProjection[ 4] = x[1]; g_mProjection[ 8] = x[2]; g_mProjection[12] = 0;
00458 g_mProjection[ 1] = y[0]; g_mProjection[ 5] = y[1]; g_mProjection[ 9] = y[2]; g_mProjection[13] = 0;
00459 g_mProjection[ 2] = l[0]; g_mProjection[ 6] = l[1]; g_mProjection[10] = l[2]; g_mProjection[14] = 0;
00460 g_mProjection[ 3] = 0; g_mProjection[ 7] = 0; g_mProjection[11] = 0; g_mProjection[15] = 1;
00461
00462 g_mProjection[ 0] = x[0]; g_mProjection[ 4] = y[0]; g_mProjection[ 8] = l[0]; g_mProjection[12] = 0;
00463 g_mProjection[ 1] = x[1]; g_mProjection[ 5] = y[1]; g_mProjection[ 9] = l[1]; g_mProjection[13] = 0;
00464 g_mProjection[ 2] = x[2]; g_mProjection[ 6] = y[2]; g_mProjection[10] = l[2]; g_mProjection[14] = 0;
00465 g_mProjection[ 3] = 0; g_mProjection[ 7] = 0; g_mProjection[11] = 0; g_mProjection[15] = 1;
00466
00467 glPushMatrix();{
00468
00469 glLoadIdentity();
00470 glScaled(1.0/(fabs(g_mProjection[0])+fabs(g_mProjection[4])+fabs(g_mProjection[8])),
00471 1.0/(fabs(g_mProjection[1])+fabs(g_mProjection[5])+fabs(g_mProjection[9])),
00472 1.0/(fabs(g_mProjection[2])+fabs(g_mProjection[6])+fabs(g_mProjection[10])));
00473 glMultMatrixf(g_mProjection);
00474 glMultMatrixd(lastProjectionMatrix);
00475
00476
00477 glGetFloatv(GL_MODELVIEW_MATRIX, g_mProjection);
00478
00479
00480 }glPopMatrix();
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508 }
00509
00515
00516 void QtGLViewer::CreateRenderTexture(GLuint& textureID, int sizeX, int sizeY, int channels, int type)
00517 {
00518 glGenTextures(1, &textureID);
00519 glBindTexture(GL_TEXTURE_2D, textureID);
00520
00521
00522 glTexImage2D(GL_TEXTURE_2D, 0, channels, sizeX, sizeY, 0, type, GL_UNSIGNED_INT, NULL);
00523
00524
00525 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
00526 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
00527 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00528 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00529 }
00530
00536
00537 void QtGLViewer::ApplyShadowMap()
00538 {
00539 #ifdef SOFA_HAVE_GLEW
00540
00541 g_Shader.TurnOn();
00542
00543
00544 glActiveTextureARB(GL_TEXTURE1_ARB);
00545 glEnable(GL_TEXTURE_2D);
00546 glBindTexture(GL_TEXTURE_2D, g_DepthTexture);
00547
00548
00549 g_Shader.SetInt(g_Shader.GetVariable("shadowMap"), 1);
00550
00551
00552
00553
00554 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00555 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00556 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00557 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00558 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB,
00559 GL_COMPARE_R_TO_TEXTURE_ARB);
00560
00561
00562
00563
00564 const float mBias[] = {0.5, 0.0, 0.0, 0.0,
00565 0.0, 0.5, 0.0, 0.0,
00566 0.0, 0.0, 0.5+g_DepthBias[0], 0.0,
00567 0.5, 0.5, 0.5+g_DepthBias[1], 1.0};
00568
00569 glMatrixMode(GL_TEXTURE);
00570
00571 glLoadMatrixf(mBias);
00572 glMultMatrixf(g_mProjection);
00573 glMultMatrixf(g_mModelView);
00574
00575
00576 glMatrixMode(GL_MODELVIEW);
00577
00578 glActiveTextureARB(GL_TEXTURE0_ARB);
00579
00580
00581
00582
00583 camera()->getModelViewMatrix( lastModelviewMatrix );
00584
00585 DisplayOBJs();
00586
00587
00588 glMatrixMode(GL_TEXTURE);
00589 glLoadIdentity();
00590 glMatrixMode(GL_MODELVIEW);
00591
00592
00593
00594 glActiveTextureARB(GL_TEXTURE1_ARB);
00595 glDisable(GL_TEXTURE_2D);
00596 glActiveTextureARB(GL_TEXTURE0_ARB);
00597
00598
00599 g_Shader.TurnOff();
00600 #endif // SOFA_HAVE_GLEW
00601 }
00602
00603
00604
00605
00606 void QtGLViewer::PrintString(void* font, char* string)
00607 {
00608 int len, i;
00609
00610 len = (int) strlen(string);
00611 for (i = 0; i < len; i++)
00612 {
00613 glutBitmapCharacter(font, string[i]);
00614 }
00615 }
00616
00617
00618
00619
00620 void QtGLViewer::Display3DText(float x, float y, float z, char* string)
00621 {
00622 char* c;
00623
00624 glPushMatrix();
00625 glTranslatef(x, y, z);
00626 for (c = string; *c != '\0'; c++)
00627 {
00628 glutStrokeCharacter(GLUT_STROKE_ROMAN, *c);
00629 }
00630 glPopMatrix();
00631 }
00632
00633
00634
00635
00636
00637 void QtGLViewer::DrawAxis(double xpos, double ypos, double zpos,
00638 double arrowSize)
00639 {
00640 float fontScale = (float) (arrowSize / 600.0);
00641
00642 Enable<GL_DEPTH_TEST> depth;
00643 Enable<GL_LIGHTING> lighting;
00644 Enable<GL_COLOR_MATERIAL> colorMat;
00645
00646 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00647 glShadeModel(GL_SMOOTH);
00648
00649
00650 glPushMatrix();
00651 glColor3f(1.0, 0.0, 0.0);
00652 glTranslated(xpos, ypos, zpos);
00653 glRotatef(90.0f, 0.0, 1.0, 0.0);
00654 gluCylinder(_tube, arrowSize / 50.0, arrowSize / 50.0, arrowSize, 10, 10);
00655 glTranslated(0.0, 0.0, arrowSize);
00656 gluCylinder(_arrow, arrowSize / 15.0, 0.0, arrowSize / 5.0, 10, 10);
00657
00658 glTranslated(-0.5 * fontScale * (double)
00659 glutStrokeWidth(GLUT_STROKE_ROMAN, 88),
00660 arrowSize / 15.0, arrowSize /
00661 5.0);
00662 glLineWidth(3.0);
00663 glScalef(fontScale, fontScale, fontScale);
00664 glutStrokeCharacter(GLUT_STROKE_ROMAN, 88);
00665 glScalef(1.0f / fontScale, 1.0f / fontScale, 1.0f / fontScale);
00666 glLineWidth(1.0f);
00667
00668 glTranslated(-xpos, -ypos, -zpos);
00669 glPopMatrix();
00670
00671
00672 glPushMatrix();
00673 glColor3f(0.0, 1.0, 0.0);
00674 glTranslated(xpos, ypos, zpos);
00675 glRotatef(-90.0f, 1.0, 0.0, 0.0);
00676 gluCylinder(_tube, arrowSize / 50.0, arrowSize / 50.0, arrowSize, 10, 10);
00677 glTranslated(0.0, 0.0, arrowSize);
00678 gluCylinder(_arrow, arrowSize / 15.0, 0.0, arrowSize / 5.0, 10, 10);
00679
00680 glTranslated(-0.5 * fontScale * (double)
00681 glutStrokeWidth(GLUT_STROKE_ROMAN, 89),
00682 arrowSize / 15.0, arrowSize /
00683 5.0);
00684 glLineWidth(3.0);
00685 glScalef(fontScale, fontScale, fontScale);
00686 glutStrokeCharacter(GLUT_STROKE_ROMAN, 89);
00687 glScalef(1.0f / fontScale, 1.0f / fontScale, 1.0f / fontScale);
00688 glLineWidth(1.0);
00689
00690 glTranslated(-xpos, -ypos, -zpos);
00691 glPopMatrix();
00692
00693
00694 glPushMatrix();
00695 glColor3f(0.0, 0.0, 1.0);
00696 glTranslated(xpos, ypos, zpos);
00697 glRotatef(0.0f, 1.0, 0.0, 0.0);
00698 gluCylinder(_tube, arrowSize / 50.0, arrowSize / 50.0, arrowSize, 10, 10);
00699 glTranslated(0.0, 0.0, arrowSize);
00700 gluCylinder(_arrow, arrowSize / 15.0, 0.0, arrowSize / 5.0, 10, 10);
00701
00702 glTranslated(-0.5 * fontScale * (double)
00703 glutStrokeWidth(GLUT_STROKE_ROMAN, 90),
00704 arrowSize / 15.0, arrowSize /
00705 5.0);
00706 glLineWidth(3.0);
00707 glScalef(fontScale, fontScale, fontScale);
00708 glutStrokeCharacter(GLUT_STROKE_ROMAN, 90);
00709 glScalef(1.0f / fontScale, 1.0f / fontScale, 1.0f / fontScale);
00710 glLineWidth(1.0);
00711
00712 glTranslated(-xpos, -ypos, -zpos);
00713 glPopMatrix();
00714 }
00715
00716
00717
00718
00719
00720 void QtGLViewer::DrawBox(Real* minBBox, Real* maxBBox, Real r)
00721 {
00722
00723 if (r==0.0)
00724 r = (Vector3(maxBBox) - Vector3(minBBox)).norm() / 500;
00725 #if 0
00726 {
00727 Enable<GL_DEPTH_TEST> depth;
00728 Disable<GL_LIGHTING> lighting;
00729 glColor3f(0.0, 1.0, 1.0);
00730 glBegin(GL_LINES);
00731 for (int corner=0; corner<4; ++corner)
00732 {
00733 glVertex3d( minBBox[0] ,
00734 (corner&1)?minBBox[1]:maxBBox[1],
00735 (corner&2)?minBBox[2]:maxBBox[2]);
00736 glVertex3d( maxBBox[0] ,
00737 (corner&1)?minBBox[1]:maxBBox[1],
00738 (corner&2)?minBBox[2]:maxBBox[2]);
00739 }
00740 for (int corner=0; corner<4; ++corner)
00741 {
00742 glVertex3d((corner&1)?minBBox[0]:maxBBox[0],
00743 minBBox[1] ,
00744 (corner&2)?minBBox[2]:maxBBox[2]);
00745 glVertex3d((corner&1)?minBBox[0]:maxBBox[0],
00746 maxBBox[1] ,
00747 (corner&2)?minBBox[2]:maxBBox[2]);
00748 }
00749
00750
00751 for (int corner=0; corner<4; ++corner)
00752 {
00753 glVertex3d((corner&1)?minBBox[0]:maxBBox[0],
00754 (corner&2)?minBBox[1]:maxBBox[1],
00755 minBBox[2] );
00756 glVertex3d((corner&1)?minBBox[0]:maxBBox[0],
00757 (corner&2)?minBBox[1]:maxBBox[1],
00758 maxBBox[2] );
00759 }
00760 glEnd();
00761 return;
00762 }
00763 #endif
00764 Enable<GL_DEPTH_TEST> depth;
00765 Enable<GL_LIGHTING> lighting;
00766 Enable<GL_COLOR_MATERIAL> colorMat;
00767
00768 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00769 glShadeModel(GL_SMOOTH);
00770
00771
00772 glColor3f(0.0, 1.0, 1.0);
00773 for (int corner=0; corner<8; ++corner)
00774 {
00775 glPushMatrix();
00776 glTranslated((corner&1)?minBBox[0]:maxBBox[0],
00777 (corner&2)?minBBox[1]:maxBBox[1],
00778 (corner&4)?minBBox[2]:maxBBox[2]);
00779 gluSphere(_sphere,2*r,20,10);
00780 glPopMatrix();
00781 }
00782
00783 glColor3f(1.0, 1.0, 0.0);
00784
00785 for (int corner=0; corner<4; ++corner)
00786 {
00787 glPushMatrix();
00788 glTranslated( minBBox[0] ,
00789 (corner&1)?minBBox[1]:maxBBox[1],
00790 (corner&2)?minBBox[2]:maxBBox[2]);
00791 glRotatef(90,0,1,0);
00792 gluCylinder(_tube, r, r, maxBBox[0] - minBBox[0], 10, 10);
00793 glPopMatrix();
00794 }
00795
00796
00797 for (int corner=0; corner<4; ++corner)
00798 {
00799 glPushMatrix();
00800 glTranslated((corner&1)?minBBox[0]:maxBBox[0],
00801 minBBox[1] ,
00802 (corner&2)?minBBox[2]:maxBBox[2]);
00803 glRotatef(-90,1,0,0);
00804 gluCylinder(_tube, r, r, maxBBox[1] - minBBox[1], 10, 10);
00805 glPopMatrix();
00806 }
00807
00808
00809 for (int corner=0; corner<4; ++corner)
00810 {
00811 glPushMatrix();
00812 glTranslated((corner&1)?minBBox[0]:maxBBox[0],
00813 (corner&2)?minBBox[1]:maxBBox[1],
00814 minBBox[2] );
00815 gluCylinder(_tube, r, r, maxBBox[2] - minBBox[2], 10, 10);
00816 glPopMatrix();
00817 }
00818 }
00819
00820
00821
00822
00823
00824
00825 void QtGLViewer::DrawXYPlane(double zo, double xmin, double xmax, double ymin,
00826 double ymax, double step)
00827 {
00828 register double x, y;
00829
00830 Enable<GL_DEPTH_TEST> depth;
00831
00832 glBegin(GL_LINES);
00833 for (x = xmin; x <= xmax; x += step)
00834 {
00835 glVertex3d(x, ymin, zo);
00836 glVertex3d(x, ymax, zo);
00837 }
00838 glEnd();
00839
00840 glBegin(GL_LINES);
00841 for (y = ymin; y <= ymax; y += step)
00842 {
00843 glVertex3d(xmin, y, zo);
00844 glVertex3d(xmax, y, zo);
00845 }
00846 glEnd();
00847 }
00848
00849
00850
00851
00852
00853
00854 void QtGLViewer::DrawYZPlane(double xo, double ymin, double ymax, double zmin,
00855 double zmax, double step)
00856 {
00857 register double y, z;
00858 Enable<GL_DEPTH_TEST> depth;
00859
00860 glBegin(GL_LINES);
00861 for (y = ymin; y <= ymax; y += step)
00862 {
00863 glVertex3d(xo, y, zmin);
00864 glVertex3d(xo, y, zmax);
00865 }
00866 glEnd();
00867
00868 glBegin(GL_LINES);
00869 for (z = zmin; z <= zmax; z += step)
00870 {
00871 glVertex3d(xo, ymin, z);
00872 glVertex3d(xo, ymax, z);
00873 }
00874 glEnd();
00875
00876 }
00877
00878
00879
00880
00881
00882
00883 void QtGLViewer::DrawXZPlane(double yo, double xmin, double xmax, double zmin,
00884 double zmax, double step)
00885 {
00886 register double x, z;
00887 Enable<GL_DEPTH_TEST> depth;
00888
00889 glBegin(GL_LINES);
00890 for (x = xmin; x <= xmax; x += step)
00891 {
00892 glVertex3d(x, yo, zmin);
00893 glVertex3d(x, yo, zmax);
00894 }
00895 glEnd();
00896
00897 glBegin(GL_LINES);
00898 for (z = zmin; z <= zmax; z += step)
00899 {
00900 glVertex3d(xmin, yo, z);
00901 glVertex3d(xmax, yo, z);
00902 }
00903 glEnd();
00904 }
00905
00906
00907
00908
00909 void QtGLViewer::DrawLogo()
00910 {
00911 glPushMatrix();
00912
00913 int w = 0;
00914 int h = 0;
00915
00916 if (texLogo && texLogo->getImage()) {
00917 h = texLogo->getImage()->getHeight();
00918 w = texLogo->getImage()->getWidth();
00919 }
00920 else return;
00921
00922 Enable <GL_TEXTURE_2D> tex;
00923 glDisable(GL_DEPTH_TEST);
00924 glMatrixMode(GL_PROJECTION);
00925 glPushMatrix();
00926 glLoadIdentity();
00927 glOrtho(-0.5, _W, -0.5, _H, -1.0, 1.0);
00928 glMatrixMode(GL_MODELVIEW);
00929 glLoadIdentity();
00930
00931 if (texLogo)
00932 texLogo->bind();
00933
00934 glColor3f(1.0f, 1.0f, 1.0f);
00935 glBegin(GL_QUADS);
00936 glTexCoord2d(0.0, 0.0);
00937 glVertex3d((_W-w)/2, (_H-h)/2, 0.0);
00938
00939 glTexCoord2d(1.0, 0.0);
00940 glVertex3d( _W-(_W-w)/2, (_H-h)/2, 0.0);
00941
00942 glTexCoord2d(1.0, 1.0);
00943 glVertex3d( _W-(_W-w)/2, _H-(_H-h)/2, 0.0);
00944
00945 glTexCoord2d(0.0, 1.0);
00946 glVertex3d((_W-w)/2, _H-(_H-h)/2, 0.0);
00947 glEnd();
00948
00949 glBindTexture(GL_TEXTURE_2D, 0);
00950
00951 glMatrixMode(GL_PROJECTION);
00952 glPopMatrix();
00953 glMatrixMode(GL_MODELVIEW);
00954 glPopMatrix();
00955 }
00956
00957
00958
00959
00960 void QtGLViewer::DisplayOBJs(bool shadowPass)
00961 {
00962 if (!groot) return;
00963
00964 Enable<GL_LIGHTING> light;
00965 Enable<GL_DEPTH_TEST> depth;
00966
00967 glShadeModel(GL_SMOOTH);
00968
00969 glColor4f(1,1,1,1);
00970 glDisable(GL_COLOR_MATERIAL);
00971
00972 if (!initTexturesDone)
00973 {
00974
00975
00976 getSimulation()->initTextures(groot);
00977
00978 initTexturesDone = true;
00979 }
00980
00981 {
00982 if (shadowPass)
00983 getSimulation()->drawShadows(groot);
00984 else
00985 getSimulation()->draw(groot);
00986 if (_axis)
00987 {
00988 DrawAxis(0.0, 0.0, 0.0, 10.0);
00989 if (sceneMinBBox[0] < sceneMaxBBox[0])
00990 DrawBox(sceneMinBBox.ptr(), sceneMaxBBox.ptr());
00991 }
00992 }
00993
00994
00995 }
00996
00997
00998
00999
01000 void QtGLViewer::DisplayMenu(void)
01001 {
01002 Disable<GL_LIGHTING> light;
01003
01004 glMatrixMode(GL_PROJECTION);
01005 glPushMatrix();
01006 glLoadIdentity();
01007 glOrtho(-0.5, _W, -0.5, _H, -1.0, 1.0);
01008 glMatrixMode(GL_MODELVIEW);
01009 glPushMatrix();
01010 glLoadIdentity();
01011
01012 glColor3f(0.3f, 0.7f, 0.95f);
01013 glRasterPos2i(_W / 2 - 5, _H - 15);
01014
01015
01016
01017 glMatrixMode(GL_PROJECTION);
01018 glPopMatrix();
01019 glMatrixMode(GL_MODELVIEW);
01020 glPopMatrix();
01021 }
01022
01023
01024
01025
01026 void QtGLViewer::DrawScene(void)
01027 {
01028
01029 camera()->getProjectionMatrix( lastProjectionMatrix );
01030
01031 camera()->getViewport( lastViewport );
01032 lastViewport[1]=0;
01033 lastViewport[3]=-lastViewport[3];
01034
01035
01036 #ifdef SOFA_HAVE_GLEW
01037 if (_shadow)
01038 {
01039
01040
01041
01042 StoreLightMatrices();
01043
01044
01045 glViewport(0, 0, (int)SHADOW_WIDTH, (int)SHADOW_HEIGHT);
01046
01047
01048 glClearColor(0.0f,0.0f,0.0f,0.0f);
01049 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01050
01051
01052 glMatrixMode(GL_PROJECTION);
01053
01054
01055 glPushMatrix();{
01056
01057 glLoadMatrixf(g_mProjection);
01058
01059
01060 glMatrixMode(GL_MODELVIEW);
01061 glPushMatrix();{
01062
01063 glLoadMatrixf(g_mModelView);
01064
01065
01066
01067 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
01068
01069
01070
01071 glEnable(GL_POLYGON_OFFSET_FILL);
01072 glDisable(GL_BLEND);
01073
01074
01075
01076 glPolygonOffset(g_DepthOffset[0], g_DepthOffset[1]);
01077
01078
01079 DisplayOBJs(true);
01080
01081
01082 glDisable(GL_BLEND);
01083
01084 glBindTexture(GL_TEXTURE_2D, g_DepthTexture);
01085
01086 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, (int)SHADOW_WIDTH, (int)SHADOW_HEIGHT);
01087
01088
01089 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
01090
01091
01092 glDisable(GL_POLYGON_OFFSET_FILL);
01093
01094 }glPopMatrix();
01095
01096 glMatrixMode(GL_PROJECTION);
01097
01098 }glPopMatrix();
01099
01100
01101 glMatrixMode(GL_MODELVIEW);
01102
01103
01104 glViewport(0, 0, GetWidth(), GetHeight());
01105
01106
01107 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01108
01109
01110
01111
01112
01113
01114
01115 glLightfv( GL_LIGHT0, GL_POSITION, _lightPosition );
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153 glMatrixMode(GL_PROJECTION);
01154 glLoadMatrixd(lastProjectionMatrix);
01155 glMatrixMode(GL_MODELVIEW);
01156 ApplyShadowMap();
01157 {
01158 Enable<GL_TEXTURE_2D> texture_on;
01159 glDisable(GL_BLEND);
01160 glBindTexture(GL_TEXTURE_2D, ShadowTextureMask);
01161 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, GetWidth(), GetHeight());
01162 }
01163 if (_background==0)
01164 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
01165 else if (_background==1)
01166 glClearColor(0.0f,0.0f,0.0f,0.0f);
01167 else if (_background==2)
01168 glClearColor(1.0f,1.0f,1.0f,1.0f);
01169 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01170 if (_background==0)
01171 DrawLogo();
01172
01173 DisplayOBJs();
01174
01175 {
01176 float ofu = GetWidth()/(float)SHADOW_MASK_SIZE;
01177 float ofv = GetHeight()/(float)SHADOW_MASK_SIZE;
01178 glActiveTextureARB(GL_TEXTURE0_ARB);
01179 glEnable(GL_TEXTURE_2D);
01180 glBindTexture(GL_TEXTURE_2D,ShadowTextureMask);
01181
01182 Disable<GL_DEPTH_TEST> dtoff;
01183 Disable<GL_LIGHTING> dlight;
01184 Enable<GL_BLEND> blend_on;
01185 glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
01186 glColor3f(1,1,1);
01187 glViewport(0, 0, GetWidth(), GetHeight());
01188 glMatrixMode(GL_PROJECTION);
01189 glPushMatrix();
01190 glLoadIdentity();
01191 glOrtho(0,1,0,1,-1,1);
01192 glMatrixMode(GL_MODELVIEW);
01193 glPushMatrix();{
01194 glLoadIdentity();
01195 glBegin(GL_QUADS);{
01196 glTexCoord2f(0,0);
01197 glVertex2f(0,0);
01198 glTexCoord2f(0,ofv);
01199 glVertex2f(0,1);
01200 glTexCoord2f(ofu,ofv);
01201 glVertex2f(1,1);
01202 glTexCoord2f(ofu,0);
01203 glVertex2f(1,0);
01204 }glEnd();
01205 }glPopMatrix();
01206 glMatrixMode(GL_PROJECTION);
01207 glPopMatrix();
01208 glMatrixMode(GL_MODELVIEW);
01209 glViewport(0, 0, GetWidth(), GetHeight());
01210 glDisable(GL_TEXTURE_2D);
01211 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01212 }
01213
01214 }
01215 else
01216 #endif
01217 {
01218 if (_background==0)
01219 DrawLogo();
01220
01221
01222 camera()->getModelViewMatrix( lastModelviewMatrix );
01223
01224
01225 if (_renderingMode == GL_RENDER)
01226 {
01227
01228 glPushMatrix();
01229 glLoadIdentity();
01230 glLightfv(GL_LIGHT0, GL_POSITION, _lightPosition);
01231 glPopMatrix();
01232 Enable<GL_LIGHT0> light0;
01233
01234 glColor3f(0.5f, 0.5f, 0.6f);
01235
01236
01237
01238 DisplayOBJs();
01239
01240 DisplayMenu();
01241 }
01242 }
01243 }
01244
01245 void QtGLViewer::viewAll()
01246 {
01247 getSimulation()->computeBBox(groot, sceneMinBBox.ptr(), sceneMaxBBox.ptr());
01248
01249 sceneBBoxIsValid = true;
01250 QGLViewer::setSceneBoundingBox( qglviewer::Vec(sceneMinBBox.ptr()),qglviewer::Vec(sceneMaxBBox.ptr()) );
01251
01252 qglviewer::Vec pos;
01253 pos[0] = 0.0;
01254 pos[1] = 0.0;
01255 pos[2] = 75.0;
01256 camera()->setPosition(pos);
01257 camera()->showEntireScene();
01258 }
01259
01260
01261
01262
01263
01264
01265 void QtGLViewer::resizeGL(int width, int height)
01266 {
01267 _W = width;
01268 _H = height;
01269
01270
01271 QGLViewer::resizeGL( width, height);
01272 camera()->setScreenWidthAndHeight(_W,_H);
01273
01274 this->resize(width, height);
01275 emit( resizeW( _W ) );
01276 emit( resizeH( _H ) );
01277 }
01278
01279
01280
01281
01282
01283 void QtGLViewer::draw()
01284 {
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304 if (_background==0)
01305 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
01306 else if (_background==1)
01307 glClearColor(0.0f,0.0f,0.0f,0.0f);
01308 else if (_background==2)
01309 glClearColor(1.0f,1.0f,1.0f,1.0f);
01310 glClearDepth(1.0);
01311 glClear(_clearBuffer);
01312
01313
01314 DrawScene();
01315
01316
01317 if (_video)
01318 {
01319 #ifdef CAPTURE_PERIOD
01320 static int counter = 0;
01321 if ((counter++ % CAPTURE_PERIOD)==0)
01322 #endif
01323 screenshot(capture.findFilename(), 2);
01324 }
01325
01326 if (_waitForRender)
01327 _waitForRender = false;
01328
01329 emit( redrawn() );
01330 }
01331
01332
01333
01334
01335
01336
01337 void QtGLViewer::keyPressEvent ( QKeyEvent * e )
01338 {
01339
01340 if( isControlPressed() )
01341 {
01342
01343 sofa::core::objectmodel::KeypressedEvent keyEvent(e->key());
01344 groot->propagateEvent(&keyEvent);
01345 }
01346 else
01347 {
01348 switch(e->key())
01349 {
01350 case Qt::Key_A:
01351 case Qt::Key_S:
01352 case Qt::Key_H:
01353 {
01354 QGLViewer::keyPressEvent(e);
01355 break;
01356 }
01357 case Qt::Key_T:
01358 {
01359 if (camera()->type() == qglviewer::Camera::ORTHOGRAPHIC)
01360 camera()->setType( qglviewer::Camera::PERSPECTIVE );
01361 else
01362 camera()->setType( qglviewer::Camera::ORTHOGRAPHIC );
01363 break;
01364 }
01365 case Qt::Key_C:
01366 {
01367 viewAll();
01368 break;
01369 }
01370 default:
01371 {
01372 SofaViewer::keyPressEvent(e);
01373 QGLViewer::keyPressEvent(e);
01374 e->ignore();
01375 }
01376 }
01377 }
01378 update();
01379 }
01380
01381
01382 void QtGLViewer::keyReleaseEvent ( QKeyEvent * e )
01383 {
01384 QGLViewer::keyReleaseEvent(e);
01385 SofaViewer::keyReleaseEvent(e);
01386 }
01387
01388 void QtGLViewer::mousePressEvent ( QMouseEvent * e )
01389 {
01390 if( ! mouseEvent(e) )
01391 QGLViewer::mousePressEvent(e);
01392 }
01393
01394 void QtGLViewer::mouseReleaseEvent ( QMouseEvent * e )
01395 {
01396 if( ! mouseEvent(e) )
01397 QGLViewer::mouseReleaseEvent(e);
01398 }
01399
01400 void QtGLViewer::mouseMoveEvent ( QMouseEvent * e )
01401 {
01402 if( ! mouseEvent(e) )
01403 QGLViewer::mouseMoveEvent(e);
01404 }
01405
01406 bool QtGLViewer::mouseEvent(QMouseEvent * e)
01407 {
01408 if(e->state()&Qt::ShiftButton)
01409 {
01410 SofaViewer::mouseEvent(e);
01411 return true;
01412 }
01413 else if (e->state()&Qt::ControlButton)
01414 {
01415 moveLaparoscopic(e);
01416 return true;
01417 }
01418 else
01419 {
01420 if (interactor!=NULL)
01421 interactor->newEvent("hide");
01422 }
01423 return false;
01424 }
01425
01426 void QtGLViewer::wheelEvent(QWheelEvent* e)
01427 {
01428 if (e->state()&Qt::ControlButton)
01429 moveLaparoscopic(e);
01430 else
01431 QGLViewer::wheelEvent(e);
01432 }
01433
01434 void QtGLViewer::moveRayPickInteractor(int eventX, int eventY)
01435 {
01436 Vec3d p0, px, py, pz;
01437 gluUnProject(eventX, lastViewport[3]-1-(eventY), 0, lastModelviewMatrix, lastProjectionMatrix, lastViewport, &(p0[0]), &(p0[1]), &(p0[2]));
01438 gluUnProject(eventX+1, lastViewport[3]-1-(eventY), 0, lastModelviewMatrix, lastProjectionMatrix, lastViewport, &(px[0]), &(px[1]), &(px[2]));
01439 gluUnProject(eventX, lastViewport[3]-1-(eventY+1), 0, lastModelviewMatrix, lastProjectionMatrix, lastViewport, &(py[0]), &(py[1]), &(py[2]));
01440 gluUnProject(eventX, lastViewport[3]-1-(eventY), 1, lastModelviewMatrix, lastProjectionMatrix, lastViewport, &(pz[0]), &(pz[1]), &(pz[2]));
01441 px -= p0;
01442 py -= p0;
01443 pz -= p0;
01444 px.normalize();
01445 py.normalize();
01446 pz.normalize();
01447 Mat4x4d transform;
01448 transform.identity();
01449 transform[0][0] = px[0];
01450 transform[1][0] = px[1];
01451 transform[2][0] = px[2];
01452 transform[0][1] = py[0];
01453 transform[1][1] = py[1];
01454 transform[2][1] = py[2];
01455 transform[0][2] = pz[0];
01456 transform[1][2] = pz[1];
01457 transform[2][2] = pz[2];
01458 transform[0][3] = p0[0];
01459 transform[1][3] = p0[1];
01460 transform[2][3] = p0[2];
01461 Mat3x3d mat; mat = transform;
01462 Quat q; q.fromMatrix(mat);
01463
01464
01465 interactor->newPosition(p0, q, transform);
01466 }
01467
01468
01469
01470
01471 void QtGLViewer::resetView()
01472 {
01473
01474 viewAll();
01475
01476 if (!sceneFileName.empty())
01477 {
01478 std::string viewFileName = sceneFileName+".view";
01479 std::ifstream in(viewFileName.c_str());
01480 if (!in.fail())
01481 {
01482 qglviewer::Vec pos;
01483 in >> pos[0];
01484 in >> pos[1];
01485 in >> pos[2];
01486
01487 camera()->setPosition(pos);
01488
01489 qglviewer::Quaternion q;
01490
01491 in >> q[0];
01492 in >> q[1];
01493 in >> q[2];
01494 in >> q[3];
01495 q.normalize();
01496
01497 camera()->setOrientation(q);
01498 camera()->showEntireScene();
01499 in.close();
01500 update();
01501 return;
01502 }
01503 }
01504 update();
01505 }
01506
01507
01508 void QtGLViewer::saveView()
01509 {
01510 if (!sceneFileName.empty())
01511 {
01512 std::string viewFileName = sceneFileName+".view";
01513 std::ofstream out(viewFileName.c_str());
01514 if (!out.fail())
01515 {
01516 out << camera()->position()[0] << " " << camera()->position()[1] << " " << camera()->position()[2] << "\n";
01517 out << camera()->orientation()[0] << " " << camera()->orientation()[1] << " " << camera()->orientation()[2] << " " << camera()->orientation()[3] << "\n";
01518 out.close();
01519 }
01520 std::cout << "View parameters saved in "<<viewFileName<<std::endl;
01521 }
01522 }
01523
01524
01525 void QtGLViewer::setSizeW( int size )
01526 {
01527 resizeGL( size, _H );
01528 updateGL();
01529 }
01530
01531 void QtGLViewer::setSizeH( int size )
01532 {
01533 resizeGL( _W, size );
01534 updateGL();
01535
01536 }
01537
01538
01539 QString QtGLViewer::helpString()
01540 {
01541
01542 QString text(
01543 "<H1>QtGLViewer</H1><hr>\
01544 <ul>\
01545 <li><b>Mouse</b>: TO NAVIGATE<br></li>\
01546 <li><b>Shift & Left Button</b>: TO PICK OBJECTS<br></li>\
01547 <li><b>A</b>: TO DRAW AXIS<br></li>\
01548 <li><b>B</b>: TO CHANGE THE BACKGROUND<br></li>\
01549 <li><b>C</b>: TO CENTER THE VIEW<br></li>\
01550 <li><b>H</b>: TO OPEN HELP of QGLViewer<br></li>\
01551 <li><b>L</b>: TO DRAW SHADOWS<br></li>\
01552 <li><b>O</b>: TO EXPORT TO .OBJ<br>\
01553 The generated files scene-time.obj and scene-time.mtl are saved in the running project directory<br></li>\
01554 <li><b>P</b>: TO SAVE A SEQUENCE OF OBJ<br>\
01555 Each time the frame is updated an obj is exported<br></li>\
01556 <li><b>R</b>: TO DRAW THE SCENE AXIS<br></li>\
01557 <li><b>T</b>: TO CHANGE BETWEEN A PERSPECTIVE OR AN ORTHOGRAPHIC CAMERA<br></li>\
01558 The captured images are saved in the running project directory under the name format capturexxxx.bmp<br></li>\
01559 <li><b>S</b>: TO SAVE A SCREENSHOT<br>\
01560 <li><b>V</b>: TO SAVE A VIDEO<br>\
01561 Each time the frame is updated a screenshot is saved<br></li>\
01562 <li><b>Esc</b>: TO QUIT ::sofa:: <br></li></ul>");
01563
01564 return text;
01565 }
01566
01567
01568
01569
01570
01571 }
01572
01573 }
01574
01575 }
01576
01577 }
01578
01579 }