Tulip  4.4.0
Better Visualization Through Research
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Groups Pages
GlMainWidget.h
1 /*
2  *
3  * This file is part of Tulip (www.tulip-software.org)
4  *
5  * Authors: David Auber and the Tulip development Team
6  * from LaBRI, University of Bordeaux 1 and Inria Bordeaux - Sud Ouest
7  *
8  * Tulip is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation, either version 3
11  * of the License, or (at your option) any later version.
12  *
13  * Tulip is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU General Public License for more details.
17  *
18  */
19 
20 #ifndef Tulip_GLMAINWIDGET_H
21 #define Tulip_GLMAINWIDGET_H
22 
23 
24 #include <QGLWidget>
25 
26 #include <tulip/tulipconf.h>
27 #include <tulip/GlScene.h>
28 #include <tulip/Graph.h>
29 
30 class QGLFramebufferObject;
31 
32 namespace tlp {
33 
34 class View;
35 class GlCompositeHierarchyManager;
36 
37 /** @ingroup OpenGL
38  * @brief This widget provide a simple system to visualize data/graph with OpenGL 3D engine
39  *
40  * This widget is an interface between Qt Widget system and tulip OpenGL engine
41  * The central object of GlMainWidget is the GlScene member
42  * @see GlScene
43  *
44  * To use this class you have to :
45  * - create a GlMainWidget
46  * - get the GlScene with getScene() function
47  * - add GlLayer and GlEntity to this scene
48  * - call centerScene() to compute a good GlCamera
49  * - see the result
50  *
51  * @see GlLayer
52  * @see GlSimpleEntity
53  *
54  *
55  * If you only want to visualize a graph, you can call the setGraph function
56  *
57  *
58  * After scene construction you can perform some operation on GlMainWidget :
59  * - Selection with doSelect() and selectGlEntities()
60  * - Image output with getImage(), createPicture(), outputSVG() and outputEPS()
61  * - Texture output with createTexture()
62  * - others operation on GlScene and QGlWidget
63  */
64 class TLP_QT_SCOPE GlMainWidget : public QGLWidget {
65  Q_OBJECT
66 
67 public:
68  /**
69  * @brief Configure the rendering process ( see render function)
70  * @see render
71  **/
73  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. **/
74  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. **/
75  };
76  Q_DECLARE_FLAGS ( RenderingOptions, RenderingOption )
77 
78  /**
79  * @brief Constructor of GlMainWidget
80  *
81  * Create a GlMainWidget with the GlScene associated to it
82  * @param parent Qt Widget parent system
83  * @param view if you want to link this GlMainWidget to a view : use this parameter
84  */
85  GlMainWidget(QWidget *parent=NULL, View *view=NULL);
86  ~GlMainWidget();
87 
88  /**
89  * @brief Get the GlScene of this GlMainWidget
90  * You have to add yours GlLayer and GlEntity to this GlScene
91  * At the construction this GlScene is empty
92  * @see GlScene
93  * @see GlScene::createLayer(const std::string &name)
94  * @see GlLayer::addGlEntity(GlSimpleEntity *entity,const std::string& name)
95  */
96  tlp::GlScene* getScene() {
97  return &scene;
98  }
99 
100  /** @brief Select nodes and edges in a region of the screen
101  *
102  * Select all nodes and edges lying in the area of the screen of given width and height,
103  * and with its upper-left corner at (x,y)
104  * @param selectedNodes filled by the method with the nodes found in the region
105  * @param selectedEdges filled by the method with the edges found in the region
106  * @param layer specify the layer in which to perform the picking
107  * @param pickNodes enable or disable the picking of nodes
108  * @param pickEdges enable or disable the picking of edges
109  */
110  void pickNodesEdges(const int x, const int y,
111  const int width, const int height,
112  std::vector<SelectedEntity> &selectedNodes, std::vector<SelectedEntity> &selectedEdges,
113  tlp::GlLayer* layer=NULL, bool pickNodes=true, bool pickEdges=true);
114 
115  /** @brief Select a node or edge at a point
116  * Try to select at point (x,y) a node in the first place then if no result try to select an edge
117  * @param type tells what has been found: NODE, EDGE
118  * @param layer specify the layer in which to perform the picking
119  * @param pickNodes enable or disable the picking of nodes
120  * @param pickEdges enable or disable the picking of edges
121  * @return true if something has been found, false otherwise
122  */
123  bool pickNodesEdges(const int x, const int y,
124  SelectedEntity &selectedEntity,
125  tlp::GlLayer* layer=NULL,
126  bool pickNodes=true, bool pickEdges=true);
127 
128  /**
129  * @deprecated this function should not be used anymore, use pickNodesEdges()
130  */
131  _DEPRECATED void doSelect(const int x, const int y,
132  const int width, const int height,
133  std::vector<tlp::node> &sNode, std::vector<tlp::edge> &sEdge,
134  tlp::GlLayer* layer=NULL);
135 
136  /**
137  * @deprecated this function should not be used anymore, use pickNodesEdges()
138  */
139  _DEPRECATED bool doSelect(const int x, const int y,
140  tlp::ElementType &type,
141  tlp::node &n,tlp::edge &e,
142  tlp::GlLayer* layer=NULL);
143 
144  /**
145  * @brief EPS output of the GlMainWidget
146  */
147  bool outputEPS(int size, int doSort, const char *filename);
148  /**
149  * @brief SVG output of the GlMainWidget
150  */
151  bool outputSVG(int size, const char* filename);
152 
153  /**
154  * @brief Compute texture size in power of two with given height and width
155  * For example if you set width to 94 and height to 256, this function set textureRealWidth to 128 and textureRealHeight to 256
156  */
157  static void getTextureRealSize(int width, int height, int &textureRealWidth, int &textureRealHeight);
158 
159  /**
160  * @brief Take a snapshot of the Widget and put it in an OpenGl texture
161  * @param width power of two number (for example 256)
162  * @param height power of two number (for example 256)
163  * You can use this texture with Tulip texture system
164  * @see GlTextureManager
165  */
166  QGLFramebufferObject *createTexture(const std::string &textureName,int width, int height);
167  /**
168  * @brief Take a snapshot of the Widget and put it in a picture
169  * @param width size
170  * @param height size
171  * @param center if true this function call a centerScene() before picture output
172  */
173  void createPicture(const std::string &pictureName,int width, int height,bool center=true);
174 
175  /**
176  * Take a snapshot of the Widget and return it
177  * @param width size
178  * @param height size
179  * @param center if true this function call a centerScene() before picture output
180  */
181  QImage createPicture(int width, int height, bool center=true);
182 
183  /**
184  * @brief Function to do picking on entities.
185  * It just calls selectEntities on the GlScene instance.
186  * @param x screen coordinates
187  * @param y screen coordinates
188  * @param width screen size
189  * @param height screen size
190  * @param pickedEntities filled with entity under the selection screen rectangle
191  * @param layer if you want to do the selection only on one GlLayer
192  */
193  bool pickGlEntities(const int x, const int y,
194  const int width, const int height,
195  std::vector<SelectedEntity>
196  &pickedEntities,
197  tlp::GlLayer* layer=NULL);
198  /**
199  * @brief Function to do picking on entities.
200  * It just calls selectEntities on the GlScene instance with a small window of twelve pixels.
201  * @param x screen coordinates
202  * @param y screen coordinates
203  * @param pickedEntities filled with entity under the selection screen rectangle
204  * @param layer if you want to do the selection only on one GlLayer
205  */
206  bool pickGlEntities(const int x, const int y,
207  std::vector<SelectedEntity>
208  &pickedEntities,
209  tlp::GlLayer* layer=NULL);
210 
211  /**
212  * @deprecated this function should not be used anymore, please use pickGlEntities() instead.
213  */
214  _DEPRECATED bool selectGlEntities(const int x, const int y,
215  const int width, const int height,
216  std::vector<GlSimpleEntity*> &pickedEntities,
217  tlp::GlLayer* layer=NULL) {
218  std::vector<SelectedEntity> entities;
219  pickGlEntities(x,y,width,height,entities,layer);
220  bool foundEntity=false;
221 
222  for(std::vector<SelectedEntity>::iterator it=entities.begin(); it!=entities.end(); ++it) {
223  if((*it).getEntityType()==SelectedEntity::SIMPLE_ENTITY_SELECTED) {
224  pickedEntities.push_back((*it).getSimpleEntity());
225  foundEntity=true;
226  }
227  }
228 
229  return foundEntity;
230  }
231 
232  /**
233  * @deprecated this function should not be used anymore, please use pickGlEntities() instead.
234  */
235  _DEPRECATED bool selectGlEntities(const int x, const int y,
236  std::vector<GlSimpleEntity*> &pickedEntities,
237  tlp::GlLayer* layer=NULL) {
238  std::vector<SelectedEntity> entities;
239  pickGlEntities(x,y,entities,layer);
240  bool foundEntity=false;
241 
242  for(std::vector<SelectedEntity>::iterator it=entities.begin(); it!=entities.end(); ++it) {
243  if((*it).getEntityType()==SelectedEntity::SIMPLE_ENTITY_SELECTED) {
244  pickedEntities.push_back((*it).getSimpleEntity());
245  foundEntity=true;
246  }
247  }
248 
249  return foundEntity;
250  }
251 
252  /**
253  * Grab the FrameBuffer of this GlMainWidget
254  * @param withAlpha use alpha chanel
255  */
256  virtual QImage grabFrameBuffer(bool withAlpha = false);
257 
258 
259  /**
260  * Extend makeCurrent function of QGLWidget to inform TextureManager and DisplayListManager of context changement
261  */
262  virtual void makeCurrent();
263 
264  /**
265  * Resize openGL view
266  */
267  void resizeGL(int w, int h);
268 
269  /**
270  * Compute interactors before drawing
271  */
272  void computeInteractors();
273 
274  /**
275  * Draw interactors
276  */
277  void drawInteractors();
278 
279  /**
280  * @brief This function performs all the rendering process of the graph.
281  * Use this function only for advanced purpose, if you want to perform simple rendering use the draw or redraw functions instead.
282  * @param options Configure the rendering process, see the RenderingOption documentation for more information on each rendering option effect.
283  * @see RenderingOption
284  * @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
285  **/
286  void render(RenderingOptions options=RenderingOptions(RenderScene|SwapBuffers), bool checkVisibility=true);
287 
288 private:
289 
290  void setupOpenGlContext();
291  void createRenderingStore(int width, int height);
292 
293  tlp::GlScene scene;
294  QRegion _visibleArea;
295  View *view;
296  int widthStored;
297  int heightStored;
298  char *renderingStore;
299  bool frameBufferStored;
300  bool useFramebufferObject;
301  QGLFramebufferObject *glFrameBuf;
302  static bool inRendering;
303  int renderingNumber;
304 
305 public slots:
306  /**
307  * Draw the GlScene and the interactors
308  */
309  void draw(bool graphChanged=true);
310  /**
311  * That function is given for optimisation purpose. If the hardware enable it,
312  * it enables to redraw only the Augmented display and the interactors and not the graph
313  * it is really usefull for interactors such as zoom box etc..
314  * Warning, if you change the graph or the porperties of element (Colors, size, etc...)
315  * applying that fonction will not display the change, in that case, use the draw function.
316  */
317  void redraw();
318 
319 
320  void closeEvent(QCloseEvent *e);
321 
322  /**
323  * @brief Convenience function that call center function on the current scene, apply a zoom (if needed) and draw the view.
324  * Same thing than
325  * @code
326  * getScene()->centerScene();
327  * getScene()->zoomFactor();
328  * draw();
329  * @endcode
330  **/
331  void centerScene(bool graphChanged = false, float zoomFactor = 1.0);
332 
333  void emitGraphChanged();
334 
335 protected slots:
336  void paintEvent( QPaintEvent* );
337 
338 signals:
339  /**
340  * This signal is emit when the GlMainWidget will be deleted
341  */
342  void closing(GlMainWidget *, QCloseEvent *);
343 
344  /**
345  * This signal is emit when GlMainWidget::redraw() is call
346  */
347  void viewRedrawn(GlMainWidget *glWidget);
348  /**
349  * This signal is emit when GlMainWidget::draw() is call
350  */
351  void viewDrawn(GlMainWidget *glWidget,bool graphChanged);
352 
353  void glResized(int w,int h);
354 
355  void graphChanged();
356 
357 public :
358 
359  /**
360  * This function return the first QGLWidget created
361  * This function is use to share OpenGL context
362  */
363  static QGLWidget* getFirstQGLWidget();
364 
365  static void clearFirstQGLWidget();
366 
367 private :
368  static QGLWidget *firstQGLWidget;
369 
370 };
371 
372 }
373 
374 
375 #endif