OpenSceneGraph set the camera at an initial position

excalibur1491 picture excalibur1491 · Jan 17, 2014 · Viewed 8.6k times · Source

I am working on OpenSceneGraph for the first time and I'm a bit lost cause the documentation is really not that clear...

So, I have this code that load a obj file with a house on it, and I have drown a little box where I want the "person" to be. So now, instead of having that box there, I would like to have the camera there, looking at the front and later on I'll to something to move the terrain around the fixed camera so that it looks like the camera is moving but the terrain is moving.

So, here is my code:

int main()
{
    osgViewer::Viewer viewer;

    viewer.setUpViewInWindow(0,0,800,800);

    osg::ref_ptr<osg::Group> root (new osg::Group);

    osg::Node* terrain = osgDB::readNodeFile(".terrain.obj");
    if(terrain == NULL) {
        return -1;
    }

    Geode* gbox = new Geode();
    gbox->addDrawable(new ShapeDrawable(new Box()));

    PositionAttitudeTransform* terrainT = new PositionAttitudeTransform();

    PositionAttitudeTransform* boxT = new PositionAttitudeTransform();
    boxT->setScale(Vec3d(50,50,50));
    boxT->setPosition(Vec3d(1000,1000,0)); 

    root->addChild(terrainT);
    root->addChild(boxT);
    terrainT->addChild(terrain);
    boxT->addChild(gbox);

    viewer.setSceneData( root.get() ); 
    viewer.addEventHandler(new osgViewer::WindowSizeHandler);
    viewer.setCameraManipulator(new osgGA::TrackballManipulator());

    viewer.realize();
    while(!viewer.done()) {
        viewer.frame(); 
    }

    return 0;
}

So this code works, it loads the the fiel correctly, puts the box where I want and I can navigate with the mouse.

Now, I just really cannot find anything to place the camera where the box is. I just can't.

Can anyone give me a hint of how to do it? It shouldn't be very hard, but I cannot find any good tutorial and the documentation the Viewer and Camera classes is really not very helpful.

Answer

Vaillancourt picture Vaillancourt · Jan 21, 2014

A couple of notes:

  • Try and give a model example that comes with OSG
  • Join all the headers required to build your code, this will make it faster for ppl who try to help you :)
  • Your code was otherwise neat and clean, which is a good thing!

Now, related to OSG:

  • OSG uses it's own implementation of smart pointers, which is osg::ref_ptr. This has to be used every time you create a new OSG object which inherits from osg::Referenced, which include nearly everything. You used it once when creating your root node, which is fine, but since all the other OSG objects you created have their destructor private, they'll create memory leaks. Of course, it's not that a big deal for this small program, but it should be a good habit to take right away. (I think there is a Quick Start Guide somewhere free in pdf format, by Paul Martz, it might help you with this.)
  • osgViewer::Viewer comes with the 'default' camera, you can get it with .getCamera(). For what you currently need, you have to set the view matrix as a look at (.setViewMatrixAsLookAt()). It takes three vectors: eye, centre and up, which are used to position and orient the camera.
  • In OSG, I have never heard the practice of keeping the camera at a fixed position and moving the world instead. You'll want to move the camera and keep the world in a fixed position to avoid any brain damage.
  • I'm not familiar with it (I haven't used it personally), but I think there is a base class named osgGA::CameraManipulator which could be used for common camera operations.
  • Good to know: osg::Camera is a osg::Transform which is a osg::Group, which means that you'll be able to put a Camera in a scene graph and only display what's underneath. Well this is a bit more advanced, but still.

Here is a copy of your code, with the box commented out, the model changed and the osg::ref_ptr added. Since you position the camera manually, you no longer need the trackball manipulator.

#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/PositionAttitudeTransform>
#include <osgGA/TrackballManipulator>
#include <osgViewer/ViewerEventHandlers>

using namespace osg;

int main()
{
    osgViewer::Viewer viewer;

    viewer.setUpViewInWindow(50,50,800,800);

    osg::ref_ptr<osg::Group> root (new osg::Group);

    osg::Node* terrain = osgDB::readNodeFile("C:\\DevTools\\OpenSceneGraph\\examples\\OpenSceneGraph-Data\\cessna.osg");
    if(terrain == nullptr) {
        return -1;
    }

    //Geode* gbox = new Geode();
    //gbox->addDrawable(new ShapeDrawable(new Box()));

    osg::ref_ptr<PositionAttitudeTransform> terrainT = new PositionAttitudeTransform();

    //PositionAttitudeTransform* boxT = new PositionAttitudeTransform();
    //boxT->setScale(Vec3d(50,50,50));
    //boxT->setPosition(Vec3d(1000,1000,0)); 

    root->addChild(terrainT);
    //root->addChild(boxT);
    terrainT->addChild(terrain);
    //boxT->addChild(gbox);

    viewer.setSceneData( root.get() ); 
    osg::ref_ptr<osgViewer::WindowSizeHandler> handler = new osgViewer::WindowSizeHandler();
    viewer.addEventHandler( handler );
//    viewer.setCameraManipulator(new osgGA::TrackballManipulator());
    Vec3d eye( 1000.0, 1000.0, 0.0 );
    Vec3d center( 0.0, 0.0, 0.0 );
    Vec3d up( 0.0, 0.0, 1.0 );

    viewer.getCamera()->setViewMatrixAsLookAt( eye, center, up );

    viewer.realize();
    while(!viewer.done()) {
        viewer.frame(); 
    }


    return 0;
}

Have fun!