Tulip  4.6.0
Better Visualization Through Research
library/tulip-gui/include/tulip/GlMainWidget.h
00001 /*
00002  *
00003  * This file is part of Tulip (www.tulip-software.org)
00004  *
00005  * Authors: David Auber and the Tulip development Team
00006  * from LaBRI, University of Bordeaux
00007  *
00008  * Tulip is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU Lesser General Public License
00010  * as published by the Free Software Foundation, either version 3
00011  * of the License, or (at your option) any later version.
00012  *
00013  * Tulip is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016  * See the GNU General Public License for more details.
00017  *
00018  */
00019 
00020 #ifndef Tulip_GLMAINWIDGET_H
00021 #define Tulip_GLMAINWIDGET_H
00022 
00023 
00024 #include <QGLWidget>
00025 
00026 #include <tulip/tulipconf.h>
00027 #include <tulip/GlScene.h>
00028 #include <tulip/Graph.h>
00029 
00030 class QGLFramebufferObject;
00031 
00032 namespace tlp {
00033 
00034 class View;
00035 class GlCompositeHierarchyManager;
00036 
00037 /** @ingroup OpenGL
00038  * @brief This widget provide a simple system to visualize data/graph with OpenGL 3D engine
00039  *
00040  * This widget is an interface between Qt Widget system and tulip OpenGL engine
00041  * The central object of GlMainWidget is the GlScene member
00042  * @see GlScene
00043  *
00044  * To use this class you have to :
00045  *   - create a GlMainWidget
00046  *   - get the GlScene with getScene() function
00047  *   - add GlLayer and GlEntity to this scene
00048  *   - call centerScene() to compute a good GlCamera
00049  *   - see the result
00050  *
00051  * @see GlLayer
00052  * @see GlSimpleEntity
00053  *
00054  *
00055  * If you only want to visualize a graph, you can call the setGraph function
00056  *
00057  *
00058  * After scene construction you can perform some operation on GlMainWidget :
00059  * - Selection with doSelect() and selectGlEntities()
00060  * - Image output with getImage(), createPicture(), outputSVG() and outputEPS()
00061  * - Texture output with createTexture()
00062  * - others operation on GlScene and QGlWidget
00063  */
00064 class TLP_QT_SCOPE GlMainWidget : public QGLWidget {
00065   Q_OBJECT
00066 
00067 public:
00068   /**
00069     * @brief Configure the rendering process ( see render function)
00070     * @see render
00071     **/
00072   enum RenderingOption {
00073     RenderScene=0x1, /** Force to render the graph even if there is a previous buffered render. You need to call this option if the graph is updated to regenerate the buffer. If not set try to use the last buffered graph render, if there is no valid buffer this flag is forced. **/
00074     SwapBuffers=0x2 /** Call the swapBuffer functions at the end of the rendering process. If the disabled it's up to you to call the swapBuffer function. **/
00075   };
00076   Q_DECLARE_FLAGS ( RenderingOptions, RenderingOption )
00077 
00078   /**
00079    * @brief Constructor of GlMainWidget
00080    *
00081    * Create a GlMainWidget with the GlScene associated to it
00082    * @param parent Qt Widget parent system
00083    * @param view if you want to link this GlMainWidget to a view : use this parameter
00084    */
00085   GlMainWidget(QWidget *parent=NULL, View *view=NULL);
00086   ~GlMainWidget();
00087 
00088   /**
00089    * @brief Get the GlScene of this GlMainWidget
00090    * You have to add yours GlLayer and GlEntity to this GlScene
00091    * At the construction this GlScene is empty
00092    * @see GlScene
00093    * @see GlScene::createLayer(const std::string &name)
00094    * @see GlLayer::addGlEntity(GlSimpleEntity *entity,const std::string& name)
00095    */
00096   tlp::GlScene* getScene() {
00097     return &scene;
00098   }
00099 
00100   /** @brief Select nodes and edges in a region of the screen
00101    *
00102    *  Select all nodes and edges lying in the area of the screen of given width and height,
00103    *  and with its upper-left corner at (x,y)
00104    *  @param selectedNodes filled by the method with the nodes found in the region
00105    *  @param selectedEdges filled by the method with the edges found in the region
00106    *  @param layer specify the layer in which to perform the picking
00107    *  @param pickNodes enable or disable the picking of nodes
00108    *  @param pickEdges enable or disable the picking of edges
00109    */
00110   void pickNodesEdges(const int x, const int y,
00111                       const int width, const int height,
00112                       std::vector<SelectedEntity> &selectedNodes, std::vector<SelectedEntity> &selectedEdges,
00113                       tlp::GlLayer* layer=NULL, bool pickNodes=true, bool pickEdges=true);
00114 
00115   /** @brief Select a node or edge at a point
00116    *  Try to select at point (x,y) a node in the first place then if no result try to select an edge
00117    *  @param type tells what has been found: NODE, EDGE
00118    *  @param layer specify the layer in which to perform the picking
00119    *  @param pickNodes enable or disable the picking of nodes
00120    *  @param pickEdges enable or disable the picking of edges
00121    *  @return true if something has been found, false otherwise
00122    */
00123   bool pickNodesEdges(const int x, const int y,
00124                       SelectedEntity &selectedEntity,
00125                       tlp::GlLayer* layer=NULL,
00126                       bool pickNodes=true, bool pickEdges=true);
00127 
00128   /**
00129    * @deprecated this function should not be used anymore, use pickNodesEdges()
00130    */
00131   _DEPRECATED void doSelect(const int x, const int y,
00132                             const int width, const int height,
00133                             std::vector<tlp::node> &sNode, std::vector<tlp::edge> &sEdge,
00134                             tlp::GlLayer* layer=NULL);
00135 
00136   /**
00137    * @deprecated this function should not be used anymore, use pickNodesEdges()
00138    */
00139   _DEPRECATED bool doSelect(const int x, const int y,
00140                             tlp::ElementType &type,
00141                             tlp::node &n,tlp::edge &e,
00142                             tlp::GlLayer* layer=NULL);
00143 
00144   /**
00145    * @brief EPS output of the GlMainWidget
00146    */
00147   bool outputEPS(int size, int doSort, const char *filename);
00148   /**
00149    * @brief SVG output of the GlMainWidget
00150    */
00151   bool outputSVG(int size, const char* filename);
00152 
00153   /**
00154    * @brief Compute texture size in power of two with given height and width
00155    * For example if you set width to 94 and height to 256, this function set textureRealWidth to 128 and textureRealHeight to 256
00156    */
00157   static void getTextureRealSize(int width, int height, int &textureRealWidth, int &textureRealHeight);
00158 
00159   /**
00160    * @brief Take a snapshot of the Widget and put it in an OpenGl texture
00161    * @param width power of two number (for example 256)
00162    * @param height power of two number (for example 256)
00163    * You can use this texture with Tulip texture system
00164    * @see GlTextureManager
00165    */
00166   QGLFramebufferObject *createTexture(const std::string &textureName,int width, int height);
00167   /**
00168    * @brief Take a snapshot of the Widget and put it in a picture
00169    * @param width size
00170    * @param height size
00171    * @param center if true this function call a centerScene() before picture output
00172    */
00173   void createPicture(const std::string &pictureName,int width, int height,bool center=true);
00174 
00175   /**
00176    * Take a snapshot of the Widget and return it
00177    * @param width size
00178    * @param height size
00179    * @param center if true this function call a centerScene() before picture output
00180    */
00181   QImage createPicture(int width, int height, bool center=true);
00182 
00183   /**
00184    * @brief Function to do picking on entities.
00185    * It just calls selectEntities on the GlScene instance.
00186    * @param x screen coordinates
00187    * @param y screen coordinates
00188    * @param width screen size
00189    * @param height screen size
00190    * @param pickedEntities filled with entity under the selection screen rectangle
00191    * @param layer if you want to do the selection only on one GlLayer
00192    */
00193   bool pickGlEntities(const int x, const int y,
00194                       const int width, const int height,
00195                       std::vector<SelectedEntity>
00196                       &pickedEntities,
00197                       tlp::GlLayer* layer=NULL);
00198   /**
00199    * @brief Function to do picking on entities.
00200    * It just calls selectEntities on the GlScene instance with a small window of twelve pixels.
00201    * @param x screen coordinates
00202    * @param y screen coordinates
00203    * @param pickedEntities filled with entity under the selection screen rectangle
00204    * @param layer if you want to do the selection only on one GlLayer
00205    */
00206   bool pickGlEntities(const int x, const int y,
00207                       std::vector<SelectedEntity>
00208                       &pickedEntities,
00209                       tlp::GlLayer* layer=NULL);
00210 
00211   /**
00212    * @deprecated this function should not be used anymore, please use pickGlEntities() instead.
00213    */
00214   _DEPRECATED bool selectGlEntities(const int x, const int y,
00215                                     const int width, const int height,
00216                                     std::vector<GlSimpleEntity*> &pickedEntities,
00217                                     tlp::GlLayer* layer=NULL) {
00218     std::vector<SelectedEntity> entities;
00219     pickGlEntities(x,y,width,height,entities,layer);
00220     bool foundEntity=false;
00221 
00222     for(std::vector<SelectedEntity>::iterator it=entities.begin(); it!=entities.end(); ++it) {
00223       if((*it).getEntityType()==SelectedEntity::SIMPLE_ENTITY_SELECTED) {
00224         pickedEntities.push_back((*it).getSimpleEntity());
00225         foundEntity=true;
00226       }
00227     }
00228 
00229     return foundEntity;
00230   }
00231 
00232   /**
00233    * @deprecated this function should not be used anymore, please use pickGlEntities() instead.
00234    */
00235   _DEPRECATED bool selectGlEntities(const int x, const int y,
00236                                     std::vector<GlSimpleEntity*> &pickedEntities,
00237                                     tlp::GlLayer* layer=NULL) {
00238     std::vector<SelectedEntity> entities;
00239     pickGlEntities(x,y,entities,layer);
00240     bool foundEntity=false;
00241 
00242     for(std::vector<SelectedEntity>::iterator it=entities.begin(); it!=entities.end(); ++it) {
00243       if((*it).getEntityType()==SelectedEntity::SIMPLE_ENTITY_SELECTED) {
00244         pickedEntities.push_back((*it).getSimpleEntity());
00245         foundEntity=true;
00246       }
00247     }
00248 
00249     return foundEntity;
00250   }
00251 
00252   /**
00253    * Grab the FrameBuffer of this GlMainWidget
00254    * @param withAlpha use alpha chanel
00255    */
00256   virtual QImage grabFrameBuffer(bool withAlpha = false);
00257 
00258 
00259   /**
00260    * Extend makeCurrent function of QGLWidget to inform TextureManager and DisplayListManager of context changement
00261    */
00262   virtual void makeCurrent();
00263 
00264   /**
00265    * Resize openGL view
00266    */
00267   void  resizeGL(int w, int h);
00268 
00269   /**
00270    * Compute interactors before drawing
00271    */
00272   void  computeInteractors();
00273 
00274   /**
00275    * Draw interactors
00276    */
00277   void  drawInteractors();
00278 
00279   /**
00280     * @brief This function performs all the rendering process of the graph.
00281     * Use this function only for advanced purpose, if you want to perform simple rendering use the draw or redraw functions instead.
00282     * @param options Configure the rendering process, see the RenderingOption documentation for more information on each rendering option effect.
00283     * @see RenderingOption
00284     * @param checkVisibility If check visibility is set as true : the engine check if GlMainWidget QWidget is visible. If set at false : the engine render the scene in all cases
00285     **/
00286   void render(RenderingOptions options=RenderingOptions(RenderScene|SwapBuffers), bool checkVisibility=true);
00287 
00288   /**
00289    * @brief Specify if the scene point of view must be kept
00290    * when changing between graphs belonging to the same hierarchy
00291    */
00292   void setKeepScenePointOfViewOnSubgraphChanging(bool);
00293   /**
00294    * @brief Returns if the scene point of view must be kept
00295    * when changing between graphs belonging to the same hierarchy
00296    */
00297   bool keepScenePointOfViewOnSubgraphChanging() const;
00298 
00299   /**
00300    * @brief Specify if an advanced technique for better scene anti-aliasing has to be activated
00301    *
00302    * That option allows to obtain a better scene antialiasing through the use of offscreen rendering and sampling.
00303    * The result rendering will look better while the performance will be slightly altered.
00304    * That option is desactivated by default. Use it with caution as it could cause crashes with some buggy OpenGL drivers.
00305    */
00306   void setAdvancedAntiAliasing(bool advancedAntiAliasing) {
00307     this->advancedAntiAliasing = advancedAntiAliasing;
00308   }
00309 
00310   /**
00311    * Returns the advanced anti-aliasing technique state
00312    */
00313   bool advancedAntiAliasingActivated() const {
00314     return advancedAntiAliasing;
00315   }
00316 
00317 private:
00318 
00319   void  setupOpenGlContext();
00320   void createRenderingStore(int width, int height);
00321   void deleteRenderingStore();
00322 
00323   tlp::GlScene scene;
00324   QRegion _visibleArea;
00325   View *view;
00326   int widthStored;
00327   int heightStored;
00328   unsigned char *renderingStore;
00329   bool frameBufferStored;
00330   bool useFramebufferObject;
00331   QGLFramebufferObject *glFrameBuf, *glFrameBuf2;
00332   static bool inRendering;
00333   bool keepPointOfViewOnSubgraphChanging;
00334   bool advancedAntiAliasing;
00335 
00336 public slots:
00337   /**
00338    * Draw the GlScene and the interactors
00339    */
00340   void draw(bool graphChanged=true);
00341   /**
00342    * That function is given for optimisation purpose. If the hardware enable it,
00343    * it enables to redraw only the Augmented display and the interactors and not the graph
00344    * it is really usefull for interactors such as zoom box etc..
00345    * Warning, if you change the graph or the porperties of element (Colors, size, etc...)
00346    * applying that fonction will not display the change, in that case, use the draw function.
00347    */
00348   void redraw();
00349 
00350 
00351   void closeEvent(QCloseEvent *e);
00352 
00353   /**
00354    * @brief Convenience function that call center function on the current scene, apply a zoom (if needed) and draw the view.
00355    * Same thing than
00356    * @code
00357    * getScene()->centerScene();
00358    * getScene()->zoomFactor();
00359    * draw();
00360    * @endcode
00361   **/
00362   void centerScene(bool graphChanged = false, float zoomFactor = 1.0);
00363 
00364   void emitGraphChanged();
00365 
00366 protected slots:
00367   void paintEvent( QPaintEvent* );
00368 
00369 signals:
00370   /**
00371    * This signal is emit when the GlMainWidget will be deleted
00372    */
00373   void closing(GlMainWidget *, QCloseEvent *);
00374 
00375   /**
00376    * This signal is emit when GlMainWidget::redraw() is call
00377    */
00378   void viewRedrawn(GlMainWidget *glWidget);
00379   /**
00380    * This signal is emit when GlMainWidget::draw() is call
00381    */
00382   void viewDrawn(GlMainWidget *glWidget,bool graphChanged);
00383 
00384   void glResized(int w,int h);
00385 
00386   void graphChanged();
00387 
00388 public :
00389 
00390   /**
00391    * This function return the first QGLWidget created
00392    * This function is use to share OpenGL context
00393    */
00394   static QGLWidget* getFirstQGLWidget();
00395 
00396   static void clearFirstQGLWidget();
00397 
00398 private :
00399   static QGLWidget *firstQGLWidget;
00400 
00401 };
00402 
00403 }
00404 
00405 
00406 #endif
 All Classes Files Functions Variables Enumerations Enumerator Properties