This short document explains how to program with OpenSceneGraph in order to control objects or the camera from external tracking. These are however general guidelines which can be used for programming many things. I present how to create an OSG node callback, how to connect to a remove VRPN tracker, and how to create a custom camera manipulator.
Visiting a node during update
Given that you have a ref to a node in the scenegraph;
You want to move it at every update. For this, you create a NodeCallback which is dedicated to your needs. So let’s define the class;
The constructor is emtpy (default NodeCallback constructor) but the ’()’ operator will be defined later. You can now (somewhere where your node is available) associate an instance of this callback to the node;
Well, now, make sure your callback does something;
Creating a VRPN client to get data from a tracker
First, you need to define a client for a remote tracker;
For later, you will need to have a some user data allocated somewhere to put the tracker info into it. We want to use it into OSG so let’s create a transformation matrix.
The VRPN update will be done by callback function, so you also need to declare this function. Notice that the function is generic, and takes a pointer to void instead of a pointer to your matrix (it is the C way to implement polymorphism). The other argument is passed by VRPN with the actual sensor data.
Now, you can create your tracker and assign it the matrix and callback function. To instanciate a new vrpn remote tracker, you just give it in argument the string describing the tracker; the string device could be “Tracker0@localhost” if a local server runs with a tracker called “Tracker0” (defined in vrpn.cfg), or in IMI case “TI1@tcp://10.59.64.96”  for a remote tracker “TI1” running on the machine whose IP is 10.59.64.96. Multiple clients (and machines) can simultaneously access to the tracker data.
You can now initialise your matrix by reading data from VRPN
Of course, we have to define what the handle_tracker callback does:
So, now, every time you call _tkr->mainloop();, the matrix _mat is updated with VRPN sensor data.
For example, you may want to set the matrix of Transform node from a VRPN tracker data: this can be done with an update visitor (see above) applied on a osg::MatrixTransform node; it is in the update visitor that the VRPN mainloop shall be called.
Setting up a custom camera manipulator
In OSG, the camera is not part of the scene graph. Therefore, it cannot be manipulated like a node with a visitor. But of course, there is another and dedicated way to do it.
First, let’s check how the camera manipulators are created and assigned to a viewer (in a main file of your OSG program);
These are the predefined manipulators of OSG. What we need is a custom implementation of one.
Here is an example which I call ’follow manipulator’ which can be used to follow a given object in the scene. Whatever happens to the transform node followed is applied to the camera. This is done by inheriting from a matrix manipulator, where we have to implement a set of virtual methods.
As you can see, the FollowManipulator class keeps a reference to a transform node and to local offset matrix; this matrix will give the relative placement of the camera to the object (e.g. translation on the -Z axis to be abble to see the object). The set of methods is to be implemented to allow OSG to use the manipulator.
Now, the more important is the ’getMatrix’ method of our matrix manipulator; this is the function called when the camera is checked in OSG.
The function ’getWorldMatrices’ (notice the plurial form) returns a vector of matrices, so we just take the first one. The other functions are pretty straightforward, and often just empty;
So, now, considering you have a pointer to an object node (e.g. osg::MatrixTransform *mynode) you can use you manipulator:
In this case, it will be activated when you hit the key ’5’. To make the last one added the active one, just do: