.. _opengl-library:

*********************
Tulip Open GL Library
*********************

.. _gl-intro:

Introduction
============

Tulip-ogl is a library for OpenGL created in order to assist the developer. It provides several functions to ease the information display whereas it is a graph or just simple geometric entities. This library is the very one used in Tulip as the rendering engine.



Qt and the QApplication
-----------------------

In its actual version, Tulip is using the application framework Qt. Such tool gives us the ability to easily create a GUI application. On a more precise note, Tulip exploits the QApplication class to manage different widgets, each one providing a specific purpose. 

In the following examples, we will use these particular objects to display the graph. If you want to execute these tutorials, your system must be able to exploit the Qt library. First, you will need a working Qt installation. This step should already be completed if you have successfully used Tulip in the past on your computer. Secondly, you must specify to your OS some pathes to include when compiling the tutorials. By default, the environmental variable *CPLUS_INCLUDE_PATH* is used to inform the compilers of such inclusions. To its value should be added the following paths (default directories):

* */usr/include/qt4*
* */usr/include/qt4/QtCore*
* */usr/include/qt4/Qt*
* */usr/include/qt4/QtGui*
* */usr/include/qt4/QtOpenGL*

This operation can be achieved with the command ::

  export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/usr/include/qt4:/usr/include/qt4/QtCore:/usr/include/qt4/Qt:/usr/include/qt4/QtGui:/usr/include/qt4/QtOpenGL

If you are unable to compile the given examples and you get an error of the form::

  fatal error: QStringList : no such file or directory

please check if *CPLUS_INCLUDE_PATH* contains the appropriate pathes.


Tulip plugins and event filters
-------------------------------

If you are willing to exploit the library at its fullest, you may want to use some of the plugins or libraries developped for Tulip. This operation is entirely feasible. Once you will have analyse the following tutorials, you will be able to combine them with the ones seen in :ref:`tulip_library_tutorial`. Just do not forget to include the lines initializing the librairies and the plugins.

Event filters, such as the ones developped for Tulip, may also be included in the window. In the examples, we will integrate the *MouseNKeysNavigator* event filter, enabling the mouse and keyboard camera commands.


A few words on the Tulip OpenGL scene construction
--------------------------------------------------

The objective of tulip-ogl's class is to be as modular as possible, giving the user a full scalable and Tulip-compatible engine to render acceptable scenes and custom augmented displays.

   
Scene and layers
~~~~~~~~~~~~~~~~

The Tulip rendering engine follows the lines set by the OpenGL library. The core of a view, the displayed interface, is the scene. It contains OpenGL information and elements, such as the camera, and hierarchies of GlEntity to display graph and augmented displays: the layers.

A layer will also contained a hierarchy of GlEntities or GlSimpleEntities, the basic constituent of the scene. If we use the example of the *Node Link Diagram* component, the standard view in Tulip, we can identify three layers : the background (2D layer), the main (graph layer) and the foreground (2D layer). In the main layer we will set the nodes and edges whereas we will use the foreground 2D layer to display the interactors interface.

In the following examples, you will start by creating GlEntities and add it in the main layer. In a second time, the examples will show you how to add a few simple shapes in the foreground with a 2D layer.


GlSimpleEntity : 2D/3D classes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GlSimpleEntity is the mother-class of every 2D/3D shape. It provides one important virtual function: draw, and one important data field: the boundingBox. By generalizing this class, you can have classes making calls to OpenGL functions within the draw function. The classes of the library are listed under :

* *GlLine* : Describes a line according to a start position, a start color, an end position and an end color.
* *GlQuad* : Describes a quad according to a position and a size, or according to four points.
* *GlRect* : Describes a rectangle according to a position and a size, or according to two points.
* *GlPolygon* : Describes a polygon according to a vector of positions.
* *GlBox* : Displays a box. This augmented display is built with 6 GlQuad.
* *GlGrid* : Displays a 3D or a 2D projection of a grid. This augmented display is built with GlLine.
* *GlCircle* : Describes a circle according to a position and a size.
* *GlMultiPolygon* : Describes a set of polygon.
* *GlComplexPolygon* : Describe a convex or concav polygon with color texture and hole
* *GlRectTextured* : Describes a textured rectangle according to a position and a size, or according to two points.
* *GlSphere* : Describes a sphere according to a position and a size.





TUTORIAL 100 : An empty scene
=============================

This first example is not really a working program. It only present the skeleton of the program which will be used in the next tutorials. Its execution will produce an empty OpenGL scene.

Code explanations
-----------------

The main function of the program starts by creating a *QApplication* instance::

	QApplication app(argc,argv);

This object must always be declared at the begining of the main function if you want to use the Tulip widget oriented GUI. 

The second function we may need to call is::

	tlp::initTulipSoftware(NULL);

This action will initialize the libraries, load the plugins, set the application runtime pathes... If you intend to use plugins in your application, this method have to be called. Beware of the call order, the QApplication creation must have already been executed.

Once the basic initializations are done, we can create the content of the *QApplication*. We will here use one of the customized object of the Tulip OpenGL library: *GlMainWidget*. According to its name, this object is the main widget, used to display the graph. ::

	GlMainWidget* mainWidget = new GlMainWidget(NULL);

The widget creation also initializes the scene that contains the different layers, composing the entire display. Here again, a personalized object, the *GlLayer*, is used::

	GlLayer* mainLayer = mainWidget->getScene()->createLayer("Main");

At this point, the objects to display can be inserted into the layers. The Tulip OpenGL library uses the aformentioned *GlEntity* objects. This example presenting an empty scene, no objects are created here, however, the other tutorials will here present the elements to integrate to the scene. 

Once the content to be displayed as been added to the layers, we enable the widget visibility::

	mainWidget->show();

For now, all the functions and call have only been made outside of the Qt application a simple call to ::

	QApplication::processEvents();

transfers all the actions realized above, such as the object creation and the layers integration to the scene, to the QApplication object.

With the objects being added to the scene, we now need to place the camera to the appropriate location to apprend the elements within. The function ::

	mainWidget->centerScene();

places and orients the camera to obtain an acceptable angle on the points of interest. The second call ::

	mainWidget->draw();

validates the elements and the camera positions in the whole scene, now ready to be displayed.

As explained earlier, the Tulip plugins and event filters can be reused. For all the example of the Tulip OpenGL library, we will add the *MouseKeysNavigator* event filter, responsible for handling the mouse and keyboard commands for the camera displacement. ::

	mainWidget->installEventFilter(new MouseNKeysNavigator);

The last call execute the QApplication, finally displaying the scene we have created in the previous steps. ::

	return app.exec();


Source code
-----------

The original source code can be downloaded via :download:`this link <./_documents/tutorial100.cpp>`.


TUTORIAL 101 : Completing the scene with GlBoxes
================================================

This example is very similar to the previous one, the only difference coming from the scene content. It is here completed with the addition of two GlBoxes objects set to the respective positions (-1, -1, -1) and (1, 1, 1). The objects sizes are set to (1, 1, 1).

.. image:: _images/Gl_tutorial101.png
    :width: 300


Code explanations
-----------------

Before adding the objects to the scene, we must create them. We start by declaring their parameters. First comes the respective objects center coordinates::

	Coord center1(-1,-1,-1);
	Coord center2(1,1,1);

then, their size::

	Size size(1,1,1);

and finally, the colors used for representing the complex shape: white for the boxes faces and black for the edges ::

	Color whiteOpaque(255, 255, 255, 255);
	Color blackOpaque(0, 0, 0, 255);

With those initialization realised and once a layer is created and added to the scene, we can declare the objects::

	GlBox *node1 = new GlBox(center1, size, whiteOpaque, blackOpaque);
	GlBox *node2 = new GlBox(center2, size, whiteOpaque, blackOpaque);

and insert them into one of the scene layers::

  mainLayer->addGlEntity(node1, "Gl Tutorial 1 : Node 1");
  mainLayer->addGlEntity(node2, "Gl Tutorial 1 : Node 2");


Source code
-----------

The full example code can be found with :download:`this link <./_documents/tutorial101.cpp>`.



TUTORIAL 102 : GlBox with transparency effect
=============================================

Here again we recycle the previous tutorial to add an new object: an enclosing transparent box.

.. image:: _images/Gl_tutorial102.png
    :width: 400


Code explanations
-----------------

The process to follow is the same as the one describe earlier for creating the GlBoxes. We start with the position, the size and the color::

  Coord centerBox(0, 0, 0);
  Size sizeBox(3.001, 3.001, 3.001);
  Color purpleTrans(155, 0, 155, 50);

Notice here the sligthly bigger box size for avoiding the possible textures misdisplays and the transparency value (forth field) specified in the color declaration.

We then create the box and add it to the layer::

  GlBox *box = new GlBox(centerBox, sizeBox, purpleTrans, blackOpaque);
  mainLayer->addGlEntity(box, "Gl Tutorial 3: Box");


Source code
-----------

Use this :download:`link <./_documents/tutorial102.cpp>` to get the example source.



TUTORIAL 103 : GlCircle and 2D Layer
====================================

Reusing again the example 101, we are willing to show a circle centered at the middle of the screen. This operation will present the use of the 2D layers and the exploitation of the viewport.

.. image:: _images/Gl_tutorial103.png
    :width: 300

Code explanation
----------------

Once the two circles have been added to the *mainLayer*, we add the following code.

First comes the creation of a new layer. Because we need it to stay static, its construction must specify the 2D mode enabling::

  GlLayer *layer2D=new GlLayer("2D layer");
  layer2D->set2DMode();
  mainWidget->getScene()->addExistingLayer(layer2D);

To realise the augmented display, some information concerning the viewport have to be noted. We get the object::

	Vector<int, 4> viewport;
	viewport = mainWidget->getScene()->getViewport();

initialize its various variables::

  // (ScreenWidth / 2, ScreenHeight / 2, 1)
  Coord circleCenter(viewport[2] / 2, viewport[3] / 2, 1);
  Color whiteTrans(255, 255, 255, 0);
  Color circleColor(100, 100, 255, 255);

and create the circle to be displayed in the middle of the screen::

  // center position, radius value, outline color, fill color, filled, outlined, starting angle and the number of segments
  GlCircle* circle = new GlCircle(circleCenter, 200., circleColor, whiteTrans, false, true, 0, 50);

Finally we add the circle to the 2D Layer::

  layer2D->addGlEntity(circle, "Gl Tutorial 3 : Circle");


Source code
-----------

Pick the source code by following :download:`this link <./_documents/tutorial103.cpp>`.



TUTORIAL 104 : 2D and Composite Layers
======================================

We will work here on a quick reboot of the example describe above, exploiting a composite layer to create an slightly more complicated figure in the augmented display.

.. image:: _images/Gl_tutorial104.png
    :width: 300


Code explanation
----------------

Starting from the previous code, we create the composite layer and a rectangle *GlRect*::

  GlComposite *composite = new GlComposite();
  GlRect* rects;
  Coord center;

To obtain the position of each square center, we use the circle equation::

  for(int i=0; i < 4; i++)
  {
    center[0] = cos((double)i * 3.14/2.0) * 200.;
    center[1] = sin((double)i * 3.14/2.0) * 200.;
    center[2] = 0;
    center = center + circleCenter;

then create and add the square to the composite entity::

    rects = new GlRect(center, 32, 32, whiteTrans, circleColor);
    composite->addGlEntity(rects, "Gl Tutorial 4 : Rect" + i+1);
  }

We finish by adding the first circle to the composite layer, itself included into the 2D layer::

	composite->addGlEntity(circle, "Gl Tutorial 4 : Circle");
	layer2D->addGlEntity(composite, "Gl Tutorial 4 : composite");


Source code
-----------

As usual, the whole example in available :download:`here <./_documents/tutorial104.cpp>`.


