Howto:Extending Canvas to support MathGL

From FlightGear wiki
Jump to navigation Jump to search
This article is a stub. You can help the wiki by expanding it.
Screen shot showing a Canvas GUI dialog with a custom MathGL element rendering a simple sine (proof-of-concept) - the point being, while simple stuff like this can certainly be renderered using our existing Canvas.Path element, more complex/mathematical expressions and functions are better handled by a dedicated plotting library, that is threaded and hardware accelerated (OpenGL+ GLSL).

MathGL is a Mathematical Graphics Library (MathGL), a collection of classes and routines for scientific plotting. [1]. MathGL is ...

  • a library for making high-quality scientific graphics under Linux and Windows
  • a library for the fast data plotting and handling of large data arrays
  • a library for working in window and console modes and for easy embedding into other programs
  • a library with large and growing set of graphics

To learn more about key concepts, see: http://mathgl.sourceforge.net/doc_en/General-concepts.html

For details, see the reference manual: https://kumisystems.dl.sourceforge.net/project/mathgl/mathgl/mathgl%202.4.4/mathgl-2.4.4.eng.pdf

For testing purposes, use any of the examples from: http://mathgl.sourceforge.net/doc_en/All-samples.html#All-samples

To integrate MathGL as a custom Canvas drawing primitive (element), the steps are basically:

  • downloading/installing MathGL locally
  • modifying $SG_SRC/CMakeLists.txt to add MathGL detection (includes & linker)
  • adding a new Canvas element to $SG_SRC/elements, e.g. named "MathGL"
    • registering the new element via the sc::Group<> registry
    • updating $FG_DATA/Nasal/canvas/api.nas to add the new element there
  • adding one of the MathGL examples to the new Canvas element
  • obtaining the raw image data from MathGL by drawing in-memory:
  • updating the osg::Image directly via osg::Image::setImage()
  • exposing useful MathGL APIs in the form of dedicated element-specific properties
  • some APIs are not easily mapped to a SGPropertyNode based structure, so that dedicated Nasal/CppBind bindings would make more sense, and be less work

This Canvas element merely sub-classes sc::Image to update the osg::Image in memory by using MathGL's GetRGBA() API to obtain the raw RGBA image and update the corresponding osg::Image/Texture in memory respectively by calling osg::Image::setImage()

Screen shot showing a Canvas GUI dialog with a custom MathGL drawing element populated via the Nasal console.
Screen shot showing a Canvas GUI dialog with a custom MathGL drawing element updated by the property browser.
This is the same custom MathGL Canvas element rendering a more complex 3D mesh/function, fully hardware accelerated using OpenGL and GLSL, including support for threaded number crunching in pthread-enabled MathGL builds
MathGL running in FlightGear
simple MathGL based 2D plotting
Complex multi-instance MathGL based plotting


You will want to add a new Canvas::Element subclass whenever you want to add support for features which cannot be currently expressed easily (or efficiently) using existing means/canvas drawing primitives (i.e. via existing elements and scripting space frameworks).

For example, this may involve projects requiring camera support, i.e. rendering scenery views to a texture, rendering 3D models to a texture or doing a complete moving map with terrain elevations/height maps (even though the latter could be implemented by sub-classing Canvas::Image to some degree).

Another good example for implementing new elements is rendering file formats like PDF, 3d models or ESRI shape files.

To create a new element, you need to create a new child class which inherits from Canvas::Element base class (or any of its child-classes, e.g. Canvas::Image) and implement the interface of the parent class by providing/overriding the correspond virtual methods.

To add a new element, these are the main steps:

  • Set up a working build environment (including simgear): Building FlightGear
  • update/pull simgear,flightgear and fgdata
  • check out a new set of topic branches for each repo: git checkout -b topic/canvas-MathGL
  • Navigate to $SG_SRC/canvas/elements
  • Create a new set of files MathGL.cxx/.hxx (as per Adding a new Canvas element)
  • add them to $SG_SRC/canvas/elements/CMakeLists.txt (as per Developing using CMake)
  • edit $SG_SRC/canvas/elements/CanvasGroup.cxx to register your new element (header and staticInit)
  • begin replacing the stubs with your own C++ code
  • map the corresponding OSG/library APIs to properties/events understood by the Canvas element (see the valueChanged() and update() methods)
  • alternatively, consider using dedicated Nasal/CppBind bindings

Below, you can find patches illustrating how to approach each of these steps using boilerplate code, which you will need to customize/replace accordingly:

Caution  This custom Canvas element requires a 3rd party library which is not currently used by SimGear/FlightGear, so that the top-level CMakeLists.txt file in $SG_SRC needs to be modified to add a corresponding findPackage() call and you also need to download/install the corresponding library for building sg/fg. In addition, the CMake module itself may need to be placed in $SG_SRC/CMakeModules:







Screen shot showing how the function to be plotted by MathGL can be interactively changed using a standard Canvas GUI dialog.