QtGLViewer.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/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 //#include <sofa/helper/system/SetDirectory.h>
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 // define this if you want video and OBJ capture to be only done once per N iteration
00062 //#define CAPTURE_PERIOD 5
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       //extern UserInterface*   GUI;
00087       //extern OBJmodel*        cubeModel;
00088       // Quaternion QtGLViewer::_newQuat;
00089 
00090 
00091 #ifdef SOFA_HAVE_GLEW
00092       // Shadow Mapping parameters
00093 
00094       // These store our width and height for the shadow texture
00095       enum { SHADOW_WIDTH = 512 };
00096       enum { SHADOW_HEIGHT = 512 };
00097       enum { SHADOW_MASK_SIZE = 2048 };
00098 
00099       // This is used to set the mode with glTexParameteri() for comparing depth values.
00100       // We use GL_COMPARE_R_TO_TEXTURE_ARB as our mode.  R is used to represent the depth value.
00101 #define GL_TEXTURE_COMPARE_MODE_ARB       0x884C
00102 
00103       // This is used to set the function with glTexParameteri() to tell OpenGL how we
00104       // will compare the depth values (we use GL_LEQUAL (less than or equal)).
00105 #define GL_TEXTURE_COMPARE_FUNC_ARB       0x884D
00106 
00107       // This mode is what will compare our depth values for shadow mapping
00108 #define GL_COMPARE_R_TO_TEXTURE_ARB       0x884E
00109 
00110       // The texture array where we store our image data
00111       GLuint g_DepthTexture;
00112 
00113       // This is our global shader object that will load the shader files
00114       GLSLShader g_Shader;
00115 
00116       //float g_DepthOffset[2] = { 3.0f, 0.0f };
00117       float g_DepthOffset[2] = { 10.0f, 0.0f };
00118       float g_DepthBias[2] = { 0.0f, 0.0f };
00119 
00120       // These are the light's matrices that need to be stored
00121       float g_mProjection[16] = {0};
00122       float g_mModelView[16] = {0};
00123       //float g_mCameraInverse[16] = {0};
00124 
00125       GLuint ShadowTextureMask;
00126 
00127       // End of Shadow Mapping Parameters
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         // Replace generic visual models with OglModel
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       // --- Constructor
00162       // ---------------------------------------------------------
00163       QtGLViewer::QtGLViewer(QWidget* parent, const char* name)
00164         : QGLViewer(parent, name)
00165       {
00166     
00167         groot = NULL;               
00168         initTexturesDone = false;
00169         // setup OpenGL mode for the window
00170         //Fl_Gl_Window::mode(FL_RGB | FL_DOUBLE | FL_DEPTH | FL_ALPHA);
00171         timerAnimate = new QTimer(this);
00172         connect( timerAnimate, SIGNAL(timeout()), this, SLOT(animate()) );
00173 
00174         //  _previousEyePos = Vector3(0.0, 0.0, 0.0);
00175         //  _zoom = 1.0;
00176         //  _zoomSpeed = 250.0;
00177         //  _panSpeed = 25.0;
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         /*_surfaceModel = NULL;
00193           _springMassView = NULL;
00194           _mapView = NULL;
00195           sphViewer = NULL;
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         //near and far plane are better placed
00230             camera()->setZNearCoefficient(0.001);
00231         camera()->setZClippingCoefficient(5);
00232       }
00233 
00234 
00235       // ---------------------------------------------------------
00236       // --- Destructor
00237       // ---------------------------------------------------------
00238       QtGLViewer::~QtGLViewer()
00239       {
00240       }
00241 
00242       // -----------------------------------------------------------------
00243       // --- OpenGL initialization method - includes light definitions, 
00244       // --- color tracking, etc.
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         //std::cout << "progname="<<sofa::gui::qt::progname<<std::endl;
00263         //sofa::helper::system::SetDirectory cwd(sofa::helper::system::SetDirectory::GetProcessFullPath(sofa::gui::qt::progname));
00264 
00265         // Define light parameters
00266         //_lightPosition[0] = 0.0f;
00267         //_lightPosition[1] = 10.0f;
00268         //_lightPosition[2] = 0.0f;
00269         //_lightPosition[3] = 1.0f;
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         // Here we initialize our multi-texturing functions
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                   // Make sure our multi-texturing extensions were loaded correctly
00306                   if(!glActiveTextureARB || !glMultiTexCoord2fARB)
00307                   {
00308                       // Print an error message and quit.
00309                       //    MessageBox(g_hWnd, "Your current setup does not support multitexturing", "Error", MB_OK);
00310                       //PostQuitMessage(0);
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         // Set light model
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         // Setup 'light 0'
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         // Enable color tracking
00335         glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
00336 
00337         // All materials hereafter have full specular reflectivity with a high shine
00338         glMaterialfv(GL_FRONT, GL_SPECULAR, specref);
00339         glMateriali(GL_FRONT, GL_SHININESS, 128);
00340 
00341         glShadeModel(GL_SMOOTH);
00342 
00343         // Define background color
00344         glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
00345 
00346         //glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00347         //Load texture for logo
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         //glEnableClientState(GL_NORMAL_ARRAY);
00353 
00354         // Turn on our light and enable color along with the light
00355         //glEnable(GL_LIGHTING);
00356         glEnable(GL_LIGHT0);
00357         //glEnable(GL_COLOR_MATERIAL);
00358 
00359 #ifdef SOFA_HAVE_GLEW
00360         // Here we allocate memory for our depth texture that will store our light's view
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             // Here we pass in our new vertex and fragment shader files to our shader object.
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         // change status so we only do this stuff once
00378         initialized = true;
00379 
00380         _beginTime = CTime::getTime();
00381 
00382         printf("\n");                   
00383     
00384     
00385         // GL_LIGHT1 follows the camera
00386         //  glMatrixMode(GL_MODELVIEW);
00387         //  glPushMatrix();
00388         //  glLoadIdentity();
00389         //  glLightfv(GL_LIGHT0, GL_POSITION, _lightPosition);
00390         //  glPopMatrix();
00391     
00392         
00393     
00394         //  camera()->setType( qglviewer::Camera::ORTHOGRAPHIC );
00395         //  camera()->setType( qglviewer::Camera::PERSPECTIVE  );
00396     
00397           }
00398 
00399         // switch to preset view
00400 
00401         resetView();
00402 
00403         // Redefine keyboard events
00404         // The default SAVE_SCREENSHOT shortcut is Ctrl+S and this shortcut is used to
00405         // save x3d file in the MainController. So we need to change it:
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         //  _lightPosition[0] =  _sceneTransform.translation[0] + 10;//*cosf(TT);
00423         //  _lightPosition[1] =  _sceneTransform.translation[1] + 10;//*sinf(2*TT);
00424         //  _lightPosition[2] =  _sceneTransform.translation[2] + 35;//
00425 
00426         //_lightPosition[0] =  1;
00427         //_lightPosition[1] =  -10;
00428         //_lightPosition[2] =  0;
00429 
00430         // Reset our current light matrices
00431         memset(g_mModelView, 0, sizeof(float)*16);
00432         memset(g_mProjection, 0, sizeof(float)*16);
00433 
00434         g_mModelView[0] = 1; // identity
00435         g_mModelView[5] = 1;
00436         g_mModelView[10] = 1;
00437         g_mModelView[15] = 1;
00438 
00439         // Using perpective shadow map for the "miner lamp" case ( i.e. light.z == 0 )
00440         // which is just a "rotation" in sceen space
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         //float lw = -_lightPosition[0] * lastProjectionMatrix[3] - _lightPosition[1] * lastProjectionMatrix[7] + lastProjectionMatrix[15];
00446         //std::cout << "lx = "<<lx<<" ly = "<<ly<<" lz = "<<lz<<" lw = "<<lw<<std::endl;
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           // Grab the current matrix that will be used for the light's projection matrix
00477           glGetFloatv(GL_MODELVIEW_MATRIX, g_mProjection);
00478 
00479           // Go back to the original matrix
00480         }glPopMatrix();
00481 
00482         /*
00483         // Let's push on a new matrix so we don't change the rest of the world
00484         glPushMatrix();{
00485 
00486         // Reset the current modelview matrix
00487         glLoadIdentity();
00488         
00489         // This is where we set the light's position and view.
00490         gluLookAt(_lightPosition[0],  _lightPosition[1],  _lightPosition[2], 
00491         _sceneTransform.translation[0],    _sceneTransform.translation[1],      _sceneTransform.translation[2],     0, 1, 0);
00492 
00493         // Now that we have the light's view, let's save the current modelview matrix.
00494         glGetFloatv(GL_MODELVIEW_MATRIX, g_mModelView);
00495 
00496         // Reset the current matrix
00497         glLoadIdentity();
00498 
00499         // Set our FOV, aspect ratio, then near and far planes for the light's view
00500         gluPerspective(90.0f, 1.0f, 4.0f, 250.0f);
00501 
00502         // Grab the current matrix that will be used for the light's projection matrix
00503         glGetFloatv(GL_MODELVIEW_MATRIX, g_mProjection);
00504 
00505         // Go back to the original matrix
00506         }glPopMatrix();
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         // Create the texture and store it on the video card
00522         glTexImage2D(GL_TEXTURE_2D, 0, channels, sizeX, sizeY, 0, type, GL_UNSIGNED_INT, NULL);
00523 
00524         // Set the texture quality
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         // Let's turn our shaders on for doing shadow mapping on our world
00541         g_Shader.TurnOn();
00542 
00543         // Turn on our texture unit for shadow mapping and bind our depth texture
00544         glActiveTextureARB(GL_TEXTURE1_ARB);
00545         glEnable(GL_TEXTURE_2D); 
00546         glBindTexture(GL_TEXTURE_2D, g_DepthTexture);
00547 
00548         // Give GLSL our texture unit that holds the shadow map
00549         g_Shader.SetInt(g_Shader.GetVariable("shadowMap"), 1);
00550         //g_Shader.SetInt(g_Shader.GetVariable("tex"), 0);
00551 
00552         // Here is where we set the mode and function for shadow mapping with shadow2DProj().
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         //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
00562 
00563         // Create our bias matrix to have a 0 to 1 ratio after clip space
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);           // The bias matrix to convert to a 0 to 1 ratio
00572         glMultMatrixf(g_mProjection);   // The light's projection matrix
00573         glMultMatrixf(g_mModelView);    // The light's modelview matrix
00574         //glMultMatrixf(g_mCameraInverse);// The inverse modelview matrix
00575 
00576         glMatrixMode(GL_MODELVIEW);         // Switch back to normal modelview mode
00577 
00578         glActiveTextureARB(GL_TEXTURE0_ARB);
00579 
00580         // Render the world that needs to be shadowed
00581 
00582 
00583         camera()->getModelViewMatrix( lastModelviewMatrix );
00584         
00585         DisplayOBJs();
00586 
00587         // Reset the texture matrix
00588         glMatrixMode(GL_TEXTURE);
00589         glLoadIdentity();
00590         glMatrixMode(GL_MODELVIEW);
00591 
00592         // Turn the first multi-texture pass off
00593     
00594         glActiveTextureARB(GL_TEXTURE1_ARB);
00595         glDisable(GL_TEXTURE_2D);
00596         glActiveTextureARB(GL_TEXTURE0_ARB);
00597 
00598         // Light expected, we need to turn our shader off since we are done
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         // --- Draw the "X" axis in red
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         // ---- Display a "X" near the tip of the arrow
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         // --- Undo transforms
00668         glTranslated(-xpos, -ypos, -zpos);
00669         glPopMatrix();
00670 
00671         // --- Draw the "Y" axis in green
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         // ---- Display a "Y" near the tip of the arrow
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         // --- Undo transforms
00690         glTranslated(-xpos, -ypos, -zpos);
00691         glPopMatrix();
00692 
00693         // --- Draw the "Z" axis in blue
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         // ---- Display a "Z" near the tip of the arrow
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         // --- Undo transforms
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         //std::cout << "box = < " << minBBox[0] << ' ' << minBBox[1] << ' ' << minBBox[2] << " >-< " << maxBBox[0] << ' ' << maxBBox[1] << ' ' << maxBBox[2] << " >"<< std::endl;
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           // --- Draw the Z edges
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         // --- Draw the corners
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         // --- Draw the X edges
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         // --- Draw the Y edges
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         // --- Draw the Z edges
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       // --- Draw a "plane" in wireframe. The "plane" is parallel to the XY axis
00823       // --- of the main coordinate system 
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       // --- Draw a "plane" in wireframe. The "plane" is parallel to the XY axis
00852       // --- of the main coordinate system 
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       // --- Draw a "plane" in wireframe. The "plane" is parallel to the XY axis
00881       // --- of the main coordinate system 
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         //glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
00969         glColor4f(1,1,1,1);
00970         glDisable(GL_COLOR_MATERIAL);
00971     
00972         if (!initTexturesDone)
00973           {
00974 //      std::cout << "-----------------------------------> initTexturesDone\n";
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         // glDisable(GL_COLOR_MATERIAL);
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         //sprintf(buffer,"FPS: %.1f\n", _frameRate.GetFPS());
01015         //PrintString(GLUT_BITMAP_HELVETICA_12, buffer);
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         //glGetDoublev(GL_MODELVIEW_MATRIX,lastModelviewMatrix);
01040 
01041         // Update the light matrices for it's current position
01042         StoreLightMatrices();
01043 
01044         // Set the current viewport to our texture size
01045         glViewport(0, 0, (int)SHADOW_WIDTH, (int)SHADOW_HEIGHT);
01046 
01047         // Clear the screen and depth buffer so we can render from the light's view
01048         glClearColor(0.0f,0.0f,0.0f,0.0f);
01049         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01050 
01051         // Now we just need to set the matrices for the light before we render
01052         glMatrixMode(GL_PROJECTION);
01053 
01054         // Push on a matrix to make sure we can restore to the old matrix easily
01055         glPushMatrix();{
01056           // Set the current projection matrix to our light's projection matrix
01057           glLoadMatrixf(g_mProjection);
01058 
01059           // Load modelview mode to set our light's modelview matrix
01060           glMatrixMode(GL_MODELVIEW);
01061           glPushMatrix();{
01062             // Load the light's modelview matrix before we render to a texture
01063             glLoadMatrixf(g_mModelView);
01064 
01065             // Since we don't care about color when rendering the depth values to
01066             // the shadow-map texture, we disable color writing to increase speed.
01067             glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 
01068 
01069             // This turns of the polygon offset functionality to fix artifacts.
01070             // Comment this out and run the program to see what artifacts I mean.
01071             glEnable(GL_POLYGON_OFFSET_FILL);
01072             glDisable(GL_BLEND);
01073 
01074             // Eliminate artifacts caused by shadow mapping
01075             //  glPolygonOffset(1.0f, 0.10f);
01076             glPolygonOffset(g_DepthOffset[0], g_DepthOffset[1]);
01077 
01078             // Render the world according to the light's view
01079             DisplayOBJs(true);
01080 
01081             // Now that the world is rendered, save the depth values to a texture
01082             glDisable(GL_BLEND);
01083             //glEnable(GL_TEXTURE_2D);
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             // We can turn color writing back on since we already stored the depth values
01089             glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 
01090 
01091             // Turn off polygon offsetting
01092             glDisable(GL_POLYGON_OFFSET_FILL);
01093 
01094           }glPopMatrix();
01095           // Go back to the projection mode and restore the original matrix
01096           glMatrixMode(GL_PROJECTION);
01097           // Restore the original projection matrix
01098         }glPopMatrix();
01099 
01100         // Go back to modelview model to start drawing like normal
01101         glMatrixMode(GL_MODELVIEW);
01102 
01103         // Restore our normal viewport size to our screen width and height
01104         glViewport(0, 0, GetWidth(), GetHeight());
01105 
01106         // Clear the color and depth bits and start over from the camera's view
01107         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01108 
01109         //glPushMatrix();{
01110         //  glLoadIdentity();
01111         //  _sceneTransform.ApplyInverse();
01112         //  glGetFloatv(GL_MODELVIEW_MATRIX, g_mCameraInverse);
01113         //}glPopMatrix();
01114 
01115         glLightfv( GL_LIGHT0, GL_POSITION, _lightPosition );
01116         /*
01117           {
01118           glEnable(GL_TEXTURE_2D);
01119           glActiveTextureARB(GL_TEXTURE0_ARB);
01120           glBindTexture(GL_TEXTURE_2D, g_Texture[SHADOW_ID]);
01121           glTexEnvi(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,  GL_REPLACE);
01122           Disable<GL_DEPTH_TEST> dtoff;
01123           Disable<GL_LIGHTING> dlight;
01124           glColor3f(1,1,1);
01125           glViewport(0, 0, 128, 128);
01126           glMatrixMode(GL_PROJECTION);
01127           glPushMatrix();
01128           glLoadIdentity();
01129           glOrtho(0,1,0,1,-1,1); 
01130           glMatrixMode(GL_MODELVIEW);
01131           glPushMatrix();{
01132           glLoadIdentity();
01133           glBegin(GL_QUADS);{
01134           glTexCoord2f(0,0);
01135           glVertex2f(0,0);
01136           glTexCoord2f(0,1);
01137           glVertex2f(0,1);
01138           glTexCoord2f(1,1);
01139           glVertex2f(1,1);
01140           glTexCoord2f(1,0);
01141           glVertex2f(1,0);
01142           }glEnd();
01143           }glPopMatrix();
01144           glMatrixMode(GL_PROJECTION);
01145           glPopMatrix();
01146           glMatrixMode(GL_MODELVIEW);
01147           glViewport(0, 0, GetWidth(), GetHeight());
01148           }
01149         */
01150 
01151 
01152         // Render the world and apply the shadow map texture to it
01153         glMatrixMode(GL_PROJECTION);
01154         glLoadMatrixd(lastProjectionMatrix);
01155         glMatrixMode(GL_MODELVIEW);
01156         ApplyShadowMap();
01157         { // NICO
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           //glTexEnvi(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,  GL_REPLACE);
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             //      // Initialize lighting
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             //          DrawXZPlane(-4.0, -20.0, 20.0, -20.0, 20.0, 1.0);
01236             //          DrawAxis(0.0, 0.0, 0.0, 10.0);
01237         
01238             DisplayOBJs();
01239 
01240             DisplayMenu();      // always needs to be the last object being drawn
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       // --- Reshape of the window, reset the projection
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         //  ctime_t beginDisplay;
01286         //ctime_t endOfDisplay;
01287 
01288         //  beginDisplay = MesureTemps();
01289 
01290         // valid() is turned off when FLTK creates a new context for this window 
01291         // or when the window resizes, and is turned on after draw() is called.  
01292         // Use this to avoid unneccessarily initializing the OpenGL context.
01293         //static double lastOrthoTransZ = 0.0;
01294         /*
01295           if (!valid())
01296           {
01297           InitGFX();        // this has to be called here since we don't know when the context is created
01298           _W = w();
01299           _H = h();
01300           reshape(_W, _H);
01301           }
01302         */
01303         // clear buffers (color and depth)
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         // draw the scene
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       // --- Handle events (mouse, keyboard, ...)
01334       // ----------------------------------------
01335 
01336 
01337       void QtGLViewer::keyPressEvent ( QKeyEvent * e )
01338       {       
01339         //  cerr<<"QtGLViewer::keyPressEvent, get "<<e->key()<<endl;
01340         if( isControlPressed() ) // pass event to the scene data structure
01341           {
01342         //cerr<<"QtGLViewer::keyPressEvent, key = "<<e->key()<<" with Control pressed "<<endl;
01343         sofa::core::objectmodel::KeypressedEvent keyEvent(e->key());
01344         groot->propagateEvent(&keyEvent);
01345           }
01346         else  // control the GUI
01347           {
01348         switch(e->key())
01349           {
01350           case Qt::Key_A: //axis
01351           case Qt::Key_S: //screenshot
01352           case Qt::Key_H: //shortcuts for screenshot and help page specified for qglviewer
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         //std::cout << p0[0]<<' '<<p0[1]<<' '<<p0[2] << " -> " << pz[0]<<' '<<pz[1]<<' '<<pz[2] << std::endl;
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     } // namespace qgl
01572 
01573       } // namespace viewer 
01574  
01575     } //namespace qt
01576 
01577   } // namespace gui
01578 
01579 } // namespace sofa

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