MIRA
|
Previous: Tutorial: Creating a 3D Visualization | Next: Tutorials for Developers |
---|
In this tutorial, we will learn how to write the same 3D visualization like in Tutorial: Creating a 3D Visualization by using mira::Visualization3D instead of mira::Visualization3DBasic as base class.
You can use mira::Visualization3D as base class whenever mira::Visualization3DBasic is too restrictive. It allows flexibility when creating a visualization but it requires some more effort.
We start by deriving our class from Visualization3D that forms the base of any 3D visualization. The meta information on that class will be used to group and display visualizations in a list view of all available visualizations. We can specify the name, the category, and a description that is displayed in the visualizations dialog.
The full working example (source code, makefile) can be found in gui/examples/tutorials/Point3Visualization.C
.
Moreover, we need to implement the setupScene() method from our base class to setup our scene:
We can compile it with the following makefile
This class is already working and can be added via the "+"-Button of the Visualization Control view. However, it is pretty useless at the moment since it will render nothing onto the screen. So lets setup our scene.
First we need another member and initialize it in the setupScene method:
Now a sphere mesh is rendered at the origin of the scenery. The position can be changed via:
However, we first need to obtain the position from a Point3f channel. Therefore, we add a ChannelProperty member and reflect it in our reflect() method:
To update the position of the point corresponding to the channel, we need to listen for changes on that channel. This is done by specifying a callback, i.e. by binding a member method using setDataChangedCallback(). This is similar to subscribing to a "normal" channel:
That was easy. But what if the coordinates in that point channel are given in a coordinate system defined by the publisher of that channel instead of the world coordinate frame ?
To render the sphere/point at its real position corresponding to the current frame of the 3D editor view, we need to take the selected editor frame and the frame of the channel into account.
To be able to do this, we need to create a new scene node where we attach our point node to.
Done. The point node is now a child of the new scene node and will be positioned relative to that node. We can now also update the position of the scene node according to the channel frame. But let's consider that the channel is only updated once in a minute.
So far, when the user changes the transform frame of the 3D editor view, the position of our point is not updated until the data in the channel changes. Besides, our data frame could be part of a transform chain where other frames get updated more often than our point channel. To overcome this limitation, we can overwrite another method of our base class - "onUpdate", that is called periodically by the GUI thread. The time span since the last call of update is passed as parameter dt.
Now our point is positioned relative to a node that gets translated to the selected frame of our editor.
You can see that compared to using the Visualization3DBasic base class, this is much more code and work to visualize a simple point. However, by using the Visualization3D base class, you have more flexibility (like visualizing multiple channels by providing multiple channel properties, creating several scene nodes...)
At the moment our visualization can be added via the "Add" button of the visualization control only. To enable drag'n'drop support, allowing us to drag the Point3f channel directly into the 3D view, we need to implement the getDataConnection() method:
This method tells the visualization view which type of data we can visualize and what is the main data channel for visualization.