[osg-users] Recommended way to render a scene from multiple independent viewpoints

838 views
Skip to first unread message

Hannes Naude

unread,
Apr 11, 2017, 7:08:59 AM4/11/17
to OpenSceneGraph Users
Hi all

I am trying to render a single scene from multiple viewpoints. I initially implemented this with a compositeviewer as per the osgthirdpersonview example. This worked fine except that my update callbacks appeared to be getting called more than once per render cycle. I assumed that the update traversal was being done for each view separately and therefore nodes that are present in multiple views will have their update callbacks called multiple times. So, at this point I tried to do the same thing but with a single View, somewhat similar to the osgCamera example. But, I do not want to add my cameras with viewer.addSlave as I want them to move independently of one another. So I tried adding them into the scene graph and giving each their own GraphicsContext, but even though the windows corresponding to these GraphicsContexts get created, it appears as if all rendering is done in a single window with multiple viewpoints being rendered over one another.

Obviously there are many ways to skin this cat, but I would appreciate some guidance on the recommended approach. To recap my requirements are :
 - Multiple cameras viewing the same scene.
 - Camera positions and orientations must be independently controlled.
 - Node update callbacks should be called only once per Node per render cycle.

Any help will be appreciated

Regards
Hannes Naude

Hannes Naude

unread,
Apr 11, 2017, 8:11:16 AM4/11/17
to OpenSceneGraph Users
I think I solved my own problem. I was planning to use 

viewer.addSlave(cam,...) 

and then use 

cam->setReferenceFrame(osg::Transform::ABSOLUTE_RF) 

to decouple the slave camera from the master. (If this is not the best approach, I would still like to hear, but it seems pretty clean)

It turned out that I did not even need the second call. I think this is because I have an update callback attached to each of the slave cameras that explicitly sets the view matrix to match the world-to-local matrix of some node in the scenegraph and thereby overrides the slaving. 

By the way, this is something else that has bothered me. The requirement for a camera to track a node in the scenegraph seems like it should be extremely common. But in order to implement this I had to write my own little NodeTracker Callback as follows: 

class NodeTracker : public NodeCallback
{
public:
   NodePath _nodepath;

   NodeTracker(Node* node):_nodepath(node->getParentalNodePaths()[0]){}

   virtual void operator()(Node* node, NodeVisitor* nv)
   {
 ref_ptr<Camera> cam=node->asCamera();
 if(cam)
 {
 Matrix mat2=cam->getViewMatrix();
 Matrix mat=computeWorldToLocal(_nodepath);
cam->setViewMatrix(mat);
 }
 traverse(node, nv);
   }
};

It feels like this is such a common requirement that something like it should be built into OSG. I had a look at the tutorial on the subject :


but it recommends a solution that seems even more generally useful and is quite verbose, yet is not included in osg. What am I missing here?

Regards
Hannes Naude

Riccardo Corsi

unread,
Apr 11, 2017, 8:26:10 AM4/11/17
to OpenSceneGraph Users
Hi Hannes,

for the camera setup you're after I recommend using a SlaveUpdateCallback, which will be called once per frame for each slave camera, allowing you to manipulate the camera position/orientation at will. 

Here's a code snippet:

// implement a slave callback to place the camera as you want
class MySlaveCallback : public osg::View::Slave::UpdateSlaveCallback
{
   // implement update method
   virtual void updateSlave(osg::View& view, osg::View::Slave& slave){ ... }
}

// add the camera as slave
slaveCam->setGraphicsContext(gc);
viewer.addSlave(slaveCam, true);

// install your callback
osg::View::Slave* slave = viewer.findSlaveForCamera(slaveCam);
slave->_updateSlaveCallback = pMirrorCallback;

Ricky

_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org


Robert Osfield

unread,
Apr 11, 2017, 9:09:25 AM4/11/17
to OpenSceneGraph Users
HI Hannes,

The CompositeViewer was written specifically for your usage case -
i.e. multiple Views.

I wouldn't recommend using slave Camera's for doing multiple views,
while possible it's just a mess in terms of management. slave
Camera's are tools for helping rendering a single view, but with a
view that is composed of several components - either spread across
multiple windows, or a view that requires multiple passes such as
distortion correction, field of view etc.

The only reason you drawback you state about using CompositeViewer is
multiple update traversals. Is this correct? If so then the
discussion should be about what problems you are having with
callbacks, as the solution will likely related to how you are doing
callbacks rather high level viewer configuration.

Robert.
> _______________________________________________
> osg-users mailing list
> osg-...@lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
_______________________________________________
osg-users mailing list
osg-...@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Hannes Naude

unread,
Apr 11, 2017, 1:48:59 PM4/11/17
to OpenSceneGraph Users
Thanks Riccardo and Robert for your inputs.

Robert, yes you are correct that the only issue I had with the CompositeViewer was that the same Node's callback would get called as many times as views that it appeared in. This means that for example if I have a simple update that would translate a node a fixed amount, then nodes that appear in mulitple views would move faster than those that appear in a single view only. Also, as I add more cameras nodes end up moving faster. 

Obviously I can fix this in the update callback itself, by checking something like simulationTime (and I would ultimately have to do this anyway to make my motion happen at the same speed, irrespective of frame rate), but I would prefer to not have the callbacks called at all when not required. 

Incidentally, I found that the (non-composite) viewer did not immediately solve this. It would only go away if all my cameras shared the exact same root node. Now I have some symbology that I wish to display on one camera, but not the others, but I managed to achieve this by setting the nodemask appropriately. 

I am not really doing anything fancy with the callbacks. I created a class which extends osg::Callback and overrode the run method to update a MatrixTransform node (via getMatrix and setMatrix). I then created another class which extends MatrixTransform and in the constructor I call 

this->setUpdateCallback

providing an instance of my callback class as the argument. Now whenever I add an instance of my MatrixTransform class to the scenegraph, it implements the motion I want. 

This seems to work, except for the multiple update problem.

Hannes


> _______________________________________________
> osg-users mailing list
> osg-users@lists.openscenegraph.org

> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
_______________________________________________
osg-users mailing list

Robert Osfield

unread,
Apr 11, 2017, 2:08:19 PM4/11/17
to OpenSceneGraph Users
HI Hannes,

The osgViewer has a mechanism for avoid multiple traversals of shared
scene graphs if mutlple View's share the same root node of the scene
graph. If shared component isn't the topmost node then the OSG has no
straight forward way to know whether a subgraph has been traversed or
not that frame. One could implement a mechanism to avoid this
visiting a node multiple times in one frame but it would be really
costly to do, an expense that would only be a benefit for a very small
number of users, but would slow performance for everyone else.

The most efficient way to avoid this multiple traversals issue is to
implement to have a custom callback that is tailored to the specific
usage case that a user has. I don't know enough about the specific
callbacks and scene graph set up you have so I can't pinpoint the best
route.

If you have a shared subgraph that you don't want traversed multiple
times per frame then use an UpdateCallback that has a frameNumber
member variable that keep track of the the frameNumber (use
NodeVisitor::getFrameStamp()'s FrameNumber) of the last traversal,
when a traversal calls the update callback you only traverse the
subgraph if the frameNumber is different and then set the frameNumber
to the present frame, if the frameNumber is the same then you just
return immediately. This custom UpdateCallback you'd place as high as
you can in your scene graph to make sure the traversal stops as soon
as possible.

Another approach is to move this frameNumber tracking into your
existing update callbacks, and simple return right away with the
frameNumber is the same. This requires a small tweak to the callbacks
but is such a small change it's generally pretty easy to integrate.

Finally you can simple make your callbacks resilient so that the are
no ill effects from being called multiple times.

Robert.
>> > osg-...@lists.openscenegraph.org
>> >
>> > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>> >
>> _______________________________________________
>> osg-users mailing list
>> osg-...@lists.openscenegraph.org
>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
>
>
> _______________________________________________
> osg-users mailing list
> osg-...@lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
_______________________________________________
osg-users mailing list
osg-...@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Hannes Naude

unread,
Apr 11, 2017, 4:54:09 PM4/11/17
to OpenSceneGraph Users
Robert

Thanks so much for your help. That makes a lot of sense. I'll go implement the approach where the traversal is stopped at the shared subgraph root.

Regards
Hannes


>> >
>> > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>> >
>> _______________________________________________
>> osg-users mailing list

>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
>
>
> _______________________________________________
> osg-users mailing list

> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
_______________________________________________
osg-users mailing list
Reply all
Reply to author
Forward
0 new messages