MIRA
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tutorial: Creating a 3D Visualization

Introduction

Visualizations are provided as plugins, i.e. shared libraries that can be dynamically loaded by miracenter or other visualization tools.

For quick and simple creation of new 3D visualization plugins, the base class mira::Visualization3DBasic is provided. In the following code examples, we will see how simple it is to write a visualization plugin to visualize a Point3f as a sphere.

For the actual rendering in 3D visualizations, we use the Ogre3D Engine (http://www.ogre3d.org/). For details how to use Ogre, please refer to its documentation on that website.

The full working example (source code, makefile) can be found in gui/examples/tutorials/Point3BasicVisualization.C.

Creating the Visualization Class

First we will create our visualization class. We can do that using the mirawizard or manually by deriving a class from mira::Visualization3DBasic:

The meta information on our 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 mira::Visualization3DBasic class is a template class where the template parameter specifies the type of channel data our plugin can visualize. So we need to specify the type of the channel. Moreover, we need to implement the setupScene() method from our base class to setup our scene:

#include <geometry/Point.h>
using namespace mira;
class Point3BasicVisualization : public Visualization3DBasic<Point3f>
{
MIRA_META_OBJECT(Point3BasicVisualization,
("Name", "Point")
("Category", "Geometry")
("Description", "Visualizes a point."))
public:
// The base class constructor needs a name how our channel will be called
Point3BasicVisualization() :
{}
// The base class already created a scene node for us - cool!
virtual void setupScene(Ogre::SceneManager* mgr, Ogre::SceneNode* node)
{
// setup our scene here
}
};

We also need a CMakeLists.txt for our plugin, which usually is created by the mirawizard.

# Include our dependencies
MIRA_REQUIRE_PACKAGE(GUIVisualization)
MIRA_ADD_LIBRARY(Point3BasicVisualization
SHARED
PACKAGE Visualizations
SOURCE
Point3BasicVisualization.C
LINK_LIBS
GUIVisualization
)

Right now we can already compile our plugin and create it in a 3D view in miracenter by either clicking on "+" in the VisualizationControl and selecting it from the plugin list or by dragging a Point3f channel to the view. The base class takes care of creating a channel property for us that allows our plugin to connect to a Point3f channel. We can change the channel our plugin uses by changing the channel property "Point" in the VisualizationControl.

Setup a Scene and Geometry

It is not surprising that nothing is shown since we did not implement anything yet. So lets create a mesh object that loads a sphere and add it to our scene node.

class Point3BasicVisualization : public Visualization3DBasic<Point3f>
{
...
Point3BasicVisualization() :
Visualization3DBasic<Point3f>("Point"),
mPoint(NULL)
{}
virtual ~Point3BasicVisualization()
{
delete mPoint;
}
virtual void setupScene(Ogre::SceneManager* mgr, Ogre::SceneNode* node)
{
mPoint = new MeshObject("Sphere.mesh", mgr, node);
}
protected:
MeshObject* mPoint;
}

So what is going on here? We have just created a mesh object and attached it to our scene node. Now a sphere mesh is rendered at the origin of the scenery. Thats all that is needed to visualize a point. But wait! What if our channel data is part of a transform tree? We need to move the point according to the target frame of the 3D view. Correct, but this is already done by the base class. It takes care of the frame id in our channel and moves the scene node accordingly. So no more work for us. We are nearly done. But remember to take the data in the point channel into account. We need to move our mesh object by the offset that is given by the point data every time the data in the channel changes. The base class provides a function we need to overwrite.

virtual void onDataChanged(ChannelRead<Point3f> point)
{
Ogre::Vector3 p = OgreUtils::toOgreVector(point->value());
mPoint->setPosition(p);
}

Thats it. Our visualization is done and working. You can add properties for color and size of the sphere and so on to improve it. Adding properties can be done similar to adding properties to Units as described in Tutorial: Using Parameters and Properties. Have fun!