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