Tulip
4.6.0
Better Visualization Through Research
|
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