[Contents] [TitleIndex] [WordIndex

Java/JOGL/OpenGL code

Renderer <-> GUI interaction

GUI can freely access the renderer methods. However, it only happens very seldom. The only case are might be to create a figure, force a redraw or use the graphic rubber box.

Due do Java limitation, Renderer can not access directly GUI. Evrything is done using the RendererProperties interface. It is used to set and retrieve all the needed informations from the GUI part. The actual implementation of the interface is the ScilabRendererProperties class. An instance of this class is created each time a new figure is created. For example the RendererProperties contains a method named setWindowSize which will modify the size of the graphic window.

ObjectGL

All the object performing OpenGL actions are derived class of this one. This class contains some methods very often used. The most useful are getGL, getGLU, getParentFigureGL and getColorMap. The getGL and getGLU allows to retrieve the opaques pointer needed for display. The parentFigure is important since it contains many state variables (factories,...). The colorMap is also always useful to know which color to use.

DrawableObjectGL

All the graphic object alse derive from this class. It contains the routines which provide fast display such as the display lists and the translation resulting from a Scilab move. There are 3 functions for the display list: startRecordDL(), endRecordDL() and displayDL(). The first two are normaly used when the draw method is called to prepare data. And the last use is used by the show function for fast display. Note that the endRecordDL function also display the recorded display list. The two methods used by the additional translations are translate and endTransalte.

DrawableClippedObjectGL

This class adds the methods used for clipping. There are four, one to clip on each direction and one to finish clipping.

AutoDrawableObjectGL

All the objects which don't use pixel coordinates derive from this class. It defines the show, initializeDrawing and endDrawing methods for the object. The final class just need to define the draw method to complete.

FigureMapper

This class contains the mapping between Scilab figure indices and the corresponding DrawableFigureGL object. This class is very often used, maybe a bit to much.

ObjectGLCleaner

Graphic objects are normally destroyed outside the OpenGL threead. There are normally no problem with that, the garbage collector will free the associated Java ressources. However, some objects hold some OpenGL ressources (such as display lists or textures) which won't be cleared by the garbage collector. These resources must manually claimed and only on the OpenGL thread. To avoid requesting the OpenGL context to become current on the Scilab thread each time some OpenGL resources are need to be freed, these ressources are scheduled for a later release. This is done by keeping a list of pointer on the object which need to be destroyed and free the resources when the next display come.

In practice, all the ObjectGL objects must define a destroy, a isUsingOGLResources and a clean method. The destroy function is called when the object is destroyed. It tries to free the OpenGL ressources if some exists (ie the isUsingOGLResources returns true) by calling the clean method. If not on the OpenGL thread, the clean is schedule to the next redraw using the ObjectCleaner

Drawers

This package contains specializations of the above classes dedicated in drawing some kind of objects. For example all objects using lines polylines, meshes, rectangles,... share similar properties such as thickness and dash mode. These class contains the shared properties. For now, there are 4 types of drawers: line drawers that draw lines representing outside shape, fill drawers which fill the shape, arrow head drawers which draw triangles on top of lines and mark drawers.

Utils package

Colormap

The utility package contains the classes used to represent the colorMap. In Scilab 5, colorMap is no longer stored in C code but rather in Java code for speed reasons. It is represented using two classes. The first one ColorMap basically does the conversion between Scilab colorIndex and its shiny RBG representation. The texturedColorMap is great improvement provided by OpenGL capabilities for the color interpolation along the colorMap. While in Scilab 4, the interpolation was performed by cutting each triangle into small pieces with an uniform color, Scilab 5 relies on OpenGL textures. This is much faster and avoid the use of costly algorithms. This class contains a 1D texture which can be applied on all triangles which need color interpolation.

Coordinate transformation

This class is also very useful. It contains all the methods needed to transform a 3D points into pixel coordinates and vice versa. Theses routines are very often used by graphic objects drawn in pixel coordinates.

The class also contains methods allowing to draw primitives above or below any others. The space is partionned in 3 layers, front, middle and back. Drawing in the front layer can be enabled using the drawFront method. Drawig in the back is enabled by the drawBack routine. To draw in the default layer, use drawMiddle.

Finally, the class contains methods which enable or disable polygon offset when needed.

Geom3D package

It contains several structures representing basic 3d primitives such as 3D vectors, planes or matrices. These could be apparently replaced by the use of the vecmath API, which is becoming a standard for 3D linear algebra (https://vecmath.dev.java.net/).

It also contains the tricky triangle decomposition class. This class has been designed for the graphic export to apply a color interpolation on a triangle. As described above, by using OpenGL, it can be sucessfully replaced by 1D texture. However in graphic export, texture can't be usedn that's why we need to keep this algorithm. For now, the algorithm is also used for the Fec object. It is used for tis abilty to draw holes in the triangles whereas texture are not (easily) able to do that. However, for a later version, it would be better to improve the texture mapping techniques in order to be able to use it also for fec objects. There are several possibilities such as using transparency, clipping planes or creating new primitives free from holes.

glTools package

It contains the representation of the clipping planes. The ClipPlane3D class defines a plane which can be clipped or unCLipped. The MovableClipPlane3D class in combination with the ClipPlane3DManager is able to update the plane equation when the viewpoint changes (specially when switching to pixel coordinates).

The GLTools class in an utility class which contains methods to enable line drawing wiht dash or simple polygon offset (use CoordinateTransformation class for a better control on polygon offset). However, its most usefull classes are usePixelCoordinates and endPixelCoordinates which switch from 3D coordinates to pixel ones.

graphic events

This package has been added in order to avoid gui events such as zoom or rotation to stack when several clicks where made on their icons. To avoid this issue, each event should be launched using a GraphicEvent. A GraphicEvent is an abstract class in which the performEvent and cancel methods must be defined. The performEvent is what the event must do (for example calling an interactive rotation). The cancel is called when an other event wants to replace the existing one. Consequenlty, after a call to cancel the event should stop quicly so other one can begin. Beware that the call is asynchronous (normally is should come from the Scilab thread).

The GraphicEventManager class is dedicated to launch events. Basically, when a new event arrives, it calls the cancel function of the current one and wait for it to finish. When the current one has ended, the new one is launched on a new thread to avoid blocking the Scilab thread. The main function of the class is launchEvent. There are also some other functions which are just shortbacks for a certain type of event (such as launchZoomEvent).

graphicSynchnronization

The only aim of the GraphicSynchnronizer class is to provide the Id the current thread. This method, but also the wait and notifyAll ones are used by the graphic synchnronization.

MarkDrawing

This package contains the routines that draw marks. The entry point is the MarkDrawer which is actually used by the MarkDrawerGL. Unlike other graphical objects which usually use a single display list, mark objects use two DL. The first one is used to display the whole set of marks. It must be recreated each time the viewPoint changes since marks are drawn using pixel coordinates. The second one is used to draw a single mark. Drawing the set of marks only consists on calling this DL on several locations.

The display of a single mark is done by MarkDrawingStrategyObjects objects. Each mark is drawn using a specific class which must define the drawMark method. In this method the object must draw the mark using OpenGL in the [-1,1] x [1,1] square. The scaling is then automatically done by the MarkDrawer.

RubberBox

This class is used to display a rubberBox above the graphic. While the rubber box is enable, the current plotted data won't refresh, the rubber box is the only thing which is displayed. The rubber box drawing is started when the activate method is called. The drawing ends with a call to deactivate. The rubber box position is updated by the setfirstPoint and setSecondPoint method which each modify two opposite points of the rubberbox. To force a new display of the rubberbox (normally just after a call to setfirstPoint and/orsetSecondPoint) call the draw method. The remainings methods are internals and should only be called from the OpenGL thread (normally forn SciRenderer class).

The drawing of the rubber box is done first by erasing the previous position and by redrawing it on its new position. Thanks to the logical operator 'equiv' (know as 'xor' mode in Scilab), the erasure can be done by redrawing the rubber on its last position. However, to be able to use this mode, it is mandatory to be in single buffer mode.

RubberBox should be an abstract class. It is actually difficult to use it direclty. in Scilab it is used in GUI in combination with mouse events. It is then possible to modify the rubberBox position with the mouse. See the class ScilabRubberBox, ClickRubberBox, PressReleaseRubberBox and ZoomRubberBox for more informations.

textRendering Package

This package has been created as a workaround for JOGL TextRenderer class's bugs and limitations. JoGL textRenderer class, is pretty easy to use. Because of its youg age, it still contains bugs. The major one is the creation of TextRenderer instance is costly and its associated ressources won't be totally freed until the OpenGL context is destroyed (ie when the window is closed). However, despite the bug report https://jogl.dev.java.net/issues/show_bug.cgi?id=348, it is not possible to change the font of a textRenderer once it has been created. Consequenlty, there must be as many textRenderers as there are fonts and font sizes. This could lead to the creation of a huge amount of TextRenderers specially with filled text whose font size vary with the with the window size.

The first workaround as been to create only a certain amount of TextRenderers for each font family. These TextRenderers can be found in the TextRendererManager class. This a big hashMap mapping font families used in Scilab with a set of TextRenderers. This set of TextRenderers are created with font sharing the family name and whose size is found in the TEXT_RENDERER_FONT_SIZES list. Consequenlty, there is only a finite number of textRenderers for each font family. But how is it possible to renderer arbitrary font size. The answer is that it not always possible.

The answer is normally interpolation. When trying to render a text, the TextRenderer having a font size just above the requested one is selected. The text is finally displayed by reducing the result given by the TextRenderer by a scale factor. For example if the closest TextRenderer is able to render a font with a size of 20 but we wants a size of 15. The algorithm actually requests the display of the text with size 20 and then scale down the result with a ration of 3/4 to get the result. A similar result could eb obtained by using the font size just below the requested one and then expand the result to get the final display. The result is howevernot as good beacause of the aliasing introduced by the expansion.

This algorithm runs pretty well but only if smoothing is enable. If nearest filtering is used, some pixels are disappearing in the scaling process and this is very bad for small fonts. Ideally, the solution could be to always enable smoothing, since it also give a better display. However on some graphic cards / graphic drivers combination (Intel and ATI mostly) the result becomes barely readable.

By default smoothing is disable and with smoothing disable it's not possible to use the interpolation technic. Consequently, by default we are stuck to the size given in the TEXT_RENDERER_FONT_SIZES list. It is however better than the 6 available font sizes of Scilab 4.x.

In the use, TextRenderers are hidden inside the SciTextRenderer class. The front end of this class share the same methods as the TextRenderer. Internaly its relies on the set of actual TextRenders located in the TextRendererManager class and perform the scaling alogorithm if possible. Consequeltly, if smoothing is enable, the use of SciTextRenders is transparent for the user, but without the memory leak bug.

In TextRendererManager class, the only really useful function is createTextRenderer which create the best SciTextRenderer able to renderer the requested font. The second argument useFractionalMetrics enable or disable the font interpolation.

The TextRendererFactory interface is used to automatically choose between SciTextRenderer which is used to display text with OpenGL and GL2PSTextRenderer which is used by the graphic export.

The last two classes FontManager and XlFontManager contains the mapping between Scilab font indices and Java font used by JOGL. There is the possibilty to add new fonts using the xlfont Scilab routine.


2022-09-08 09:27