QtViewer.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This program is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU General Public License as published by the Free  *
00007 * Software Foundation; either version 2 of the License, or (at your option)   *
00008 * any later version.                                                          *
00009 *                                                                             *
00010 * This program is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
00013 * more details.                                                               *
00014 *                                                                             *
00015 * You should have received a copy of the GNU General Public License along     *
00016 * with this program; if not, write to the Free Software Foundation, Inc., 51  *
00017 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
00018 *******************************************************************************
00019 *                            SOFA :: Applications                             *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
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 //#include <sofa/helper/system/SetDirectory.h>
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 // define this if you want video and OBJ capture to be only done once per N iteration
00058 //#define CAPTURE_PERIOD 5
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       //extern UserInterface*   GUI;
00084       //extern OBJmodel*        cubeModel;
00085 
00086 
00087       // Mouse Interactor
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       // Shadow Mapping parameters
00097 
00098       // These store our width and height for the shadow texture
00099       enum { SHADOW_WIDTH = 512 };
00100       enum { SHADOW_HEIGHT = 512 };
00101       enum { SHADOW_MASK_SIZE = 2048 };
00102 
00103       // This is used to set the mode with glTexParameteri() for comparing depth values.
00104       // We use GL_COMPARE_R_TO_TEXTURE_ARB as our mode.  R is used to represent the depth value.
00105 #define GL_TEXTURE_COMPARE_MODE_ARB       0x884C
00106 
00107       // This is used to set the function with glTexParameteri() to tell OpenGL how we
00108       // will compare the depth values (we use GL_LEQUAL (less than or equal)).
00109 #define GL_TEXTURE_COMPARE_FUNC_ARB       0x884D
00110 
00111       // This mode is what will compare our depth values for shadow mapping
00112 #define GL_COMPARE_R_TO_TEXTURE_ARB       0x884E
00113 
00114       // The texture array where we store our image data
00115       GLuint g_DepthTexture;
00116 
00117       // This is our global shader object that will load the shader files
00118       GLSLShader g_Shader;
00119 
00120       //float g_DepthOffset[2] = { 3.0f, 0.0f };
00121       float g_DepthOffset[2] = { 10.0f, 0.0f };
00122       float g_DepthBias[2] = { 0.0f, 0.0f };
00123 
00124       // These are the light's matrices that need to be stored
00125       float g_mProjection[16] = {0};
00126       float g_mModelView[16] = {0};
00127       //float g_mCameraInverse[16] = {0};
00128 
00129       GLuint ShadowTextureMask;
00130 
00131       // End of Shadow Mapping Parameters
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         // Replace generic visual models with OglModel
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       // --- Constructor
00166       // ---------------------------------------------------------
00167       QtViewer::QtViewer(QWidget* parent, const char* name)
00168         : QGLWidget(parent, name)
00169       {
00170 
00171 
00172         groot = NULL;
00173         initTexturesDone = false;
00174         // setup OpenGL mode for the window
00175         //Fl_Gl_Window::mode(FL_RGB | FL_DOUBLE | FL_DEPTH | FL_ALPHA);
00176         timerAnimate = new QTimer(this);
00177         //connect( timerAnimate, SIGNAL(timeout()), this, SLOT(animate()) );
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         /*_surfaceModel = NULL;
00201           _springMassView = NULL;
00202           _mapView = NULL;
00203           sphViewer = NULL;
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         // init trackball rotation matrix / quaternion
00226         _newTrackball.ComputeQuaternion(0.0, 0.0, 0.0, 0.0);
00227         _newQuat = _newTrackball.GetQuaternion();
00228 
00230         // Interactor //
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       // --- Destructor
00248       // ---------------------------------------------------------
00249       QtViewer::~QtViewer()
00250       {
00251       }
00252 
00253       // -----------------------------------------------------------------
00254       // --- OpenGL initialization method - includes light definitions,
00255       // --- color tracking, etc.
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         //std::cout << "progname=" << sofa::gui::qt::progname << std::endl;
00271         //sofa::helper::system::SetDirectory cwd(sofa::helper::system::SetDirectory::GetProcessFullPath(sofa::gui::qt::progname));
00272 
00273         // Define light parameters
00274         //_lightPosition[0] = 0.0f;
00275         //_lightPosition[1] = 10.0f;
00276         //_lightPosition[2] = 0.0f;
00277         //_lightPosition[3] = 1.0f;
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                   // Here we initialize our multi-texturing functions
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         // Set light model
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         // Setup 'light 0'
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         // Enable color tracking
00332         glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
00333 
00334         // All materials hereafter have full specular reflectivity with a high shine
00335         glMaterialfv(GL_FRONT, GL_SPECULAR, specref);
00336         glMateriali(GL_FRONT, GL_SHININESS, 128);
00337 
00338         glShadeModel(GL_SMOOTH);
00339 
00340         // Define background color
00341         //      glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
00342 
00343         //glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00344         //Load texture for logo
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         //glEnableClientState(GL_NORMAL_ARRAY);
00350 
00351         // Turn on our light and enable color along with the light
00352         //glEnable(GL_LIGHTING);
00353         glEnable(GL_LIGHT0);
00354         //glEnable(GL_COLOR_MATERIAL);
00355 
00356 #ifdef SOFA_HAVE_GLEW
00357         // Here we allocate memory for our depth texture that will store our light's view
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             // Here we pass in our new vertex and fragment shader files to our shader object.
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         // change status so we only do this stuff once
00375         initialized = true;
00376 
00377         _beginTime = CTime::getTime();
00378 
00379         printf("GL initialized\n");
00380           }
00381 
00382         // switch to preset view
00383         resetView();
00384       }
00385 
00386       // ---------------------------------------------------------
00387       // ---
00388       // ---------------------------------------------------------
00389 
00395 
00396       void QtViewer::StoreLightMatrices()
00397       {
00398         //  _lightPosition[0] =  _sceneTransform.translation[0] + 10;//*cosf(TT);
00399         //  _lightPosition[1] =  _sceneTransform.translation[1] + 10;//*sinf(2*TT);
00400         //  _lightPosition[2] =  _sceneTransform.translation[2] + 35;//
00401 
00402         //_lightPosition[0] =  1;
00403         //_lightPosition[1] =  -10;
00404         //_lightPosition[2] =  0;
00405 
00406         // Reset our current light matrices
00407         memset(g_mModelView, 0, sizeof(float)*16);
00408         memset(g_mProjection, 0, sizeof(float)*16);
00409 
00410         g_mModelView[0] = 1; // identity
00411         g_mModelView[5] = 1;
00412         g_mModelView[10] = 1;
00413         g_mModelView[15] = 1;
00414 
00415         // Using perpective shadow map for the "miner lamp" case ( i.e. light.z == 0 )
00416         // which is just a "rotation" in sceen space
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         //float lw = -_lightPosition[0] * lastProjectionMatrix[3] - _lightPosition[1] * lastProjectionMatrix[7] + lastProjectionMatrix[15];
00422         //std::cout << "lx = "<<lx<<" ly = "<<ly<<" lz = "<<lz<<" lw = "<<lw<<std::endl;
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           // Grab the current matrix that will be used for the light's projection matrix
00453           glGetFloatv(GL_MODELVIEW_MATRIX, g_mProjection);
00454 
00455           // Go back to the original matrix
00456         }glPopMatrix();
00457 
00458         /*
00459         // Let's push on a new matrix so we don't change the rest of the world
00460         glPushMatrix();{
00461 
00462         // Reset the current modelview matrix
00463         glLoadIdentity();
00464 
00465         // This is where we set the light's position and view.
00466         gluLookAt(_lightPosition[0],  _lightPosition[1],  _lightPosition[2],
00467         _sceneTransform.translation[0],    _sceneTransform.translation[1],      _sceneTransform.translation[2],     0, 1, 0);
00468 
00469         // Now that we have the light's view, let's save the current modelview matrix.
00470         glGetFloatv(GL_MODELVIEW_MATRIX, g_mModelView);
00471 
00472         // Reset the current matrix
00473         glLoadIdentity();
00474 
00475         // Set our FOV, aspect ratio, then near and far planes for the light's view
00476         gluPerspective(90.0f, 1.0f, 4.0f, 250.0f);
00477 
00478         // Grab the current matrix that will be used for the light's projection matrix
00479         glGetFloatv(GL_MODELVIEW_MATRIX, g_mProjection);
00480 
00481         // Go back to the original matrix
00482         }glPopMatrix();
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         // Create the texture and store it on the video card
00498         glTexImage2D(GL_TEXTURE_2D, 0, channels, sizeX, sizeY, 0, type, GL_UNSIGNED_INT, NULL);
00499 
00500         // Set the texture quality
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         // Let's turn our shaders on for doing shadow mapping on our world
00517         g_Shader.TurnOn();
00518 
00519         // Turn on our texture unit for shadow mapping and bind our depth texture
00520         glActiveTextureARB(GL_TEXTURE1_ARB);
00521         glEnable(GL_TEXTURE_2D);
00522         glBindTexture(GL_TEXTURE_2D, g_DepthTexture);
00523 
00524         // Give GLSL our texture unit that holds the shadow map
00525         g_Shader.SetInt(g_Shader.GetVariable("shadowMap"), 1);
00526         //g_Shader.SetInt(g_Shader.GetVariable("tex"), 0);
00527 
00528         // Here is where we set the mode and function for shadow mapping with shadow2DProj().
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         //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
00538 
00539         // Create our bias matrix to have a 0 to 1 ratio after clip space
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);           // The bias matrix to convert to a 0 to 1 ratio
00548         glMultMatrixf(g_mProjection);   // The light's projection matrix
00549         glMultMatrixf(g_mModelView);    // The light's modelview matrix
00550         //glMultMatrixf(g_mCameraInverse);// The inverse modelview matrix
00551 
00552         glMatrixMode(GL_MODELVIEW);         // Switch back to normal modelview mode
00553 
00554         glActiveTextureARB(GL_TEXTURE0_ARB);
00555 
00556         // Render the world that needs to be shadowed
00557 
00558         glPushMatrix();
00559         {
00560           glLoadIdentity();
00561           _sceneTransform.Apply();
00562           glGetDoublev(GL_MODELVIEW_MATRIX,lastModelviewMatrix);
00563           DisplayOBJs();
00564         }
00565         glPopMatrix();
00566 
00567         // Reset the texture matrix
00568         glMatrixMode(GL_TEXTURE);
00569         glLoadIdentity();
00570         glMatrixMode(GL_MODELVIEW);
00571 
00572         // Turn the first multi-texture pass off
00573 
00574         glActiveTextureARB(GL_TEXTURE1_ARB);
00575         glDisable(GL_TEXTURE_2D);
00576         glActiveTextureARB(GL_TEXTURE0_ARB);
00577 
00578         // Light expected, we need to turn our shader off since we are done
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         // --- Draw the "X" axis in red
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         // ---- Display a "X" near the tip of the arrow
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         // --- Undo transforms
00648         glTranslated(-xpos, -ypos, -zpos);
00649         glPopMatrix();
00650 
00651         // --- Draw the "Y" axis in green
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         // ---- Display a "Y" near the tip of the arrow
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         // --- Undo transforms
00670         glTranslated(-xpos, -ypos, -zpos);
00671         glPopMatrix();
00672 
00673         // --- Draw the "Z" axis in blue
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         // ---- Display a "Z" near the tip of the arrow
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         // --- Undo transforms
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         //std::cout << "box = < " << minBBox[0] << ' ' << minBBox[1] << ' ' << minBBox[2] << " >-< " << maxBBox[0] << ' ' << maxBBox[1] << ' ' << maxBBox[2] << " >"<< std::endl;
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           // --- Draw the Z edges
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         // --- Draw the corners
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         // --- Draw the X edges
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         // --- Draw the Y edges
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         // --- Draw the Z edges
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       // --- Draw a "plane" in wireframe. The "plane" is parallel to the XY axis
00803       // --- of the main coordinate system
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       // --- Draw a "plane" in wireframe. The "plane" is parallel to the XY axis
00832       // --- of the main coordinate system
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       // --- Draw a "plane" in wireframe. The "plane" is parallel to the XY axis
00861       // --- of the main coordinate system
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         //glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
00945         glColor4f(1,1,1,1);
00946         glDisable(GL_COLOR_MATERIAL);
00947 
00948         if (!initTexturesDone)
00949           {
00950 //      std::cout << "-----------------------------------> initTexturesDone\n";
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         // glDisable(GL_COLOR_MATERIAL);
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         //sprintf(buffer,"FPS: %.1f\n", _frameRate.GetFPS());
00993         //PrintString(GLUT_BITMAP_HELVETICA_12, buffer);
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         //glGetDoublev(GL_MODELVIEW_MATRIX,lastModelviewMatrix);
01014 
01015         // Update the light matrices for it's current position
01016         StoreLightMatrices();
01017 
01018         // Set the current viewport to our texture size
01019         glViewport(0, 0, (int)SHADOW_WIDTH, (int)SHADOW_HEIGHT);
01020 
01021         // Clear the screen and depth buffer so we can render from the light's view
01022         glClearColor(0.0f,0.0f,0.0f,0.0f);
01023         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01024 
01025         // Now we just need to set the matrices for the light before we render
01026         glMatrixMode(GL_PROJECTION);
01027 
01028         // Push on a matrix to make sure we can restore to the old matrix easily
01029         glPushMatrix();{
01030           // Set the current projection matrix to our light's projection matrix
01031           glLoadMatrixf(g_mProjection);
01032 
01033           // Load modelview mode to set our light's modelview matrix
01034           glMatrixMode(GL_MODELVIEW);
01035           glPushMatrix();{
01036             // Load the light's modelview matrix before we render to a texture
01037             glLoadMatrixf(g_mModelView);
01038 
01039             // Since we don't care about color when rendering the depth values to
01040             // the shadow-map texture, we disable color writing to increase speed.
01041             glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
01042 
01043             // This turns of the polygon offset functionality to fix artifacts.
01044             // Comment this out and run the program to see what artifacts I mean.
01045             glEnable(GL_POLYGON_OFFSET_FILL);
01046             glDisable(GL_BLEND);
01047 
01048             // Eliminate artifacts caused by shadow mapping
01049             //  glPolygonOffset(1.0f, 0.10f);
01050             glPolygonOffset(g_DepthOffset[0], g_DepthOffset[1]);
01051 
01052             _sceneTransform.Apply();
01053             // Render the world according to the light's view
01054             DisplayOBJs(true);
01055 
01056             // Now that the world is rendered, save the depth values to a texture
01057             glDisable(GL_BLEND);
01058             //glEnable(GL_TEXTURE_2D);
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             // We can turn color writing back on since we already stored the depth values
01064             glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
01065 
01066             // Turn off polygon offsetting
01067             glDisable(GL_POLYGON_OFFSET_FILL);
01068 
01069           }glPopMatrix();
01070           // Go back to the projection mode and restore the original matrix
01071           glMatrixMode(GL_PROJECTION);
01072           // Restore the original projection matrix
01073         }glPopMatrix();
01074 
01075         // Go back to modelview model to start drawing like normal
01076         glMatrixMode(GL_MODELVIEW);
01077 
01078         // Restore our normal viewport size to our screen width and height
01079         glViewport(0, 0, GetWidth(), GetHeight());
01080 
01081         // Clear the color and depth bits and start over from the camera's view
01082         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01083 
01084         //glPushMatrix();{
01085         //  glLoadIdentity();
01086         //  _sceneTransform.ApplyInverse();
01087         //  glGetFloatv(GL_MODELVIEW_MATRIX, g_mCameraInverse);
01088         //}glPopMatrix();
01089 
01090         glLightfv( GL_LIGHT0, GL_POSITION, _lightPosition );
01091         /*
01092           {
01093           glEnable(GL_TEXTURE_2D);
01094           glActiveTextureARB(GL_TEXTURE0_ARB);
01095           glBindTexture(GL_TEXTURE_2D, g_Texture[SHADOW_ID]);
01096           glTexEnvi(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,  GL_REPLACE);
01097           Disable<GL_DEPTH_TEST> dtoff;
01098           Disable<GL_LIGHTING> dlight;
01099           glColor3f(1,1,1);
01100           glViewport(0, 0, 128, 128);
01101           glMatrixMode(GL_PROJECTION);
01102           glPushMatrix();
01103           glLoadIdentity();
01104           glOrtho(0,1,0,1,-1,1);
01105           glMatrixMode(GL_MODELVIEW);
01106           glPushMatrix();{
01107           glLoadIdentity();
01108           glBegin(GL_QUADS);{
01109           glTexCoord2f(0,0);
01110           glVertex2f(0,0);
01111           glTexCoord2f(0,1);
01112           glVertex2f(0,1);
01113           glTexCoord2f(1,1);
01114           glVertex2f(1,1);
01115           glTexCoord2f(1,0);
01116           glVertex2f(1,0);
01117           }glEnd();
01118           }glPopMatrix();
01119           glMatrixMode(GL_PROJECTION);
01120           glPopMatrix();
01121           glMatrixMode(GL_MODELVIEW);
01122           glViewport(0, 0, GetWidth(), GetHeight());
01123           }
01124         */
01125 
01126 
01127         // Render the world and apply the shadow map texture to it
01128         glMatrixMode(GL_PROJECTION);
01129         glLoadMatrixd(lastProjectionMatrix);
01130         glMatrixMode(GL_MODELVIEW);
01131         ApplyShadowMap();
01132         { // NICO
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     //  glPushMatrix();
01148         _sceneTransform.Apply();
01149         DisplayOBJs();
01150 //      glPopMatrix();
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           //glTexEnvi(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,  GL_REPLACE);
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             // Initialize lighting
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             //  DrawXZPlane(-4.0, -20.0, 20.0, -20.0, 20.0, 1.0);
01214             //  DrawAxis(0.0, 0.0, 0.0, 10.0);
01215 
01216             DisplayOBJs();
01217 
01218             DisplayMenu();      // always needs to be the last object being drawn
01219         }
01220         }
01221       }
01222 
01223 
01224 
01225       // ---------------------------------------------------------
01226       // --- Reshape of the window, reset the projection
01227       // ---------------------------------------------------------
01228       void QtViewer::resizeGL(int width, int height)
01229       {
01230 
01231         _W = width;
01232         _H = height;
01233 
01234         //  std::cout << "GL window: " <<width<<"x"<<height <<std::endl;
01235 
01236         calcProjection();
01237         this->resize(width, height);
01238         emit( resizeW( _W ) );
01239         emit( resizeH( _H ) );
01240       }
01241 
01242 
01243       // ---------------------------------------------------------
01244       // --- Reshape of the window, reset the projection
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         //if (!sceneBBoxIsValid)
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; // add some margin
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         //std::cout << "Z = ["<<zNear<<" - "<<zFar<<"]\n";
01311           }
01312         xNear = 0.35*zNear;
01313         yNear = 0.35*zNear;
01314         offset = 0.001*zNear;       // for foreground and background planes
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         //float ratio = zFar/(zNear*20);
01356                 Vector3 tcenter = _sceneTransform * center;
01357                 // find Z so that dot(tcenter,tcenter-(0,0,Z))==0
01358                 // tc.x*tc.x+tc.y*tc.y+tc.z*(tc.z-Z) = 0
01359                 // Z = (tc.x*tc.x+tc.y*tc.y+tc.z*tc.z)/tc.z
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         //  ctime_t beginDisplay;
01392         //ctime_t endOfDisplay;
01393 
01394         //  beginDisplay = MesureTemps();
01395 
01396         // valid() is turned off when FLTK creates a new context for this window
01397         // or when the window resizes, and is turned on after draw() is called.
01398         // Use this to avoid unneccessarily initializing the OpenGL context.
01399         //static double lastOrthoTransZ = 0.0;
01400         /*
01401           if (!valid())
01402           {
01403           InitGFX();        // this has to be called here since we don't know when the context is created
01404           _W = w();
01405           _H = h();
01406           reshape(_W, _H);
01407           }
01408         */
01409         // clear buffers (color and depth)
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         // draw the scene
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         // Mouse Interaction
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             // Conjugate calculation of the scene orientation quaternion
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       // --- Handle events (mouse, keyboard, ...)
01573       // ----------------------------------------
01574 
01575 
01576       void QtViewer::keyPressEvent ( QKeyEvent * e )
01577       {
01578         if( isControlPressed() ) // pass event to the scene data structure
01579           {
01580     //  cerr<<"QtViewer::keyPressEvent, key = "<<e->key()<<" with Control pressed "<<endl;
01581         if (groot)
01582           {
01583             sofa::core::objectmodel::KeypressedEvent keyEvent(e->key());
01584             groot->propagateEvent(&keyEvent);
01585           }
01586           }
01587         else  // control the GUI
01588           switch(e->key())
01589         {
01590 
01591 
01592         case Qt::Key_C:
01593           {
01594             // --- switch interaction mode
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       // ---------------------- Here are the mouse controls for the scene  ----------------------
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             // Mouse left button is pushed
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             // Mouse left button is released
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             // Mouse left button is pushed
01708             if (e->button() == Qt::LeftButton)
01709               {
01710             _translationMode = XY_TRANSLATION;
01711             _mouseInteractorSavedPosX = eventX;
01712             _mouseInteractorSavedPosY = eventY;
01713             _mouseInteractorMoving = true;
01714               }
01715             // Mouse right button is pushed
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             // Mouse left button is released
01727             if ((e->button() == Qt::LeftButton) && (_translationMode == XY_TRANSLATION))
01728               {
01729             _mouseInteractorMoving = false;
01730               }
01731             // Mouse right button is released
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             // Mouse left button is pushed
01761             if (e->button() == Qt::LeftButton)
01762               {
01763             _navigationMode = BTLEFT_MODE;
01764             _mouseInteractorMoving = true;
01765             _mouseInteractorSavedPosX = eventX;
01766             _mouseInteractorSavedPosY = eventY;
01767               }
01768             // Mouse right button is pushed
01769             else if (e->button() == Qt::RightButton)
01770               {
01771             _navigationMode = BTRIGHT_MODE;
01772             _mouseInteractorMoving = true;
01773             _mouseInteractorSavedPosX = eventX;
01774             _mouseInteractorSavedPosY = eventY;
01775               }
01776             // Mouse middle button is pushed
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             // Mouse left button is released
01792             if (e->button() == Qt::LeftButton)
01793               {
01794             if (_mouseInteractorMoving)
01795               {
01796                 _mouseInteractorMoving = false;
01797               }
01798               }
01799             // Mouse right button is released
01800             else if (e->button() == Qt::RightButton)
01801               {
01802             if (_mouseInteractorMoving)
01803               {
01804                 _mouseInteractorMoving = false;
01805               }
01806               }
01807             // Mouse middle button is released
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             //g_DepthBias[0] += dx*0.01;
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             // rotate with left button
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             // zoom with right button
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             // translate with middle button (if it exists)
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             // Mouse left button is released
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             // Mouse right button is released
01928             else if (e->button() == Qt::RightButton)
01929               {
01930             if (_moving && _navigationMode == PAN_MODE)
01931               {
01932                 _moving = false;
01933               }
01934               }
01935             // Mouse middle button is released
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               case FL_MOUSEWHEEL:
01948               // it is also possible to zoom with mouse wheel (if it exists)
01949               if (Fl::event_button() == FL_MOUSEWHEEL)
01950               {
01951               _navigationMode = ZOOM_MODE;
01952               _moving = true;
01953               _mouseX = 0;
01954               _mouseY = 0;
01955               eventX = 0;
01956               eventY = 10 * Fl::event_dy();
01957               _previousEyePos[2] = _sceneTransform.translation[2];
01958               }
01959               break;
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         //std::cout << p0[0]<<' '<<p0[1]<<' '<<p0[2] << " -> " << pz[0]<<' '<<pz[1]<<' '<<pz[2] << std::endl;
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         //ResetScene();
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     }// namespace qt
02113 
02114       } // namespace viewer
02115 
02116     }
02117 
02118   } // namespace gui
02119 
02120 } // namespace sofa

Generated on Sun Nov 23 02:28:37 2008 for Sofa by  doxygen 1.5.7.1