Version 2 (modified by osg, 7 years ago)

Added menu

Node Mask Overview

(Wiki editing note: Code needs conversion to osgViewer)
(Wiki editing note: Add link to complete source code at bottom)

This example creates a scene with a terrain model a tank model and a cube. The tank and a cube are under the same transform. There are two views. The main view is the usual osgProducer::viewer - viewpoint is controlled via mouse/keyboard. The bottom middle quarter of the screen is a top down view. For the main view we want to show the terrain and the tank model but not the cube. For the top down view we want to display the terrain and the cube but not the tank model. (Sort of like a command and control view where we would display an icon rather than the geometry.)

Random good things to know

  • Camera's are rendered and accessed in alphabetical order - important for overlapping cameras.

Here's the ugly code:

    #include <osg/PositionAttitudeTransform>
    #include <osg/Group>
    #include <osg/Node>
    #include <osgDB/ReadFile>
    #include <osgDB/FileUtils>
    #include <osgProducer/Viewer>

    #include <osgText/Font>
    #include <osgText/Text>
    #include <osg/MatrixTransform>
    #include <osg/Geode>
    #include <osg/Projection>
    #include <osg/ShapeDrawable>
    #include <osg/Geometry>
    #include <osg/MatrixTransform>
    #include <osg/PositionAttitudeTransform>
    #include <osgUtil/CullVisitor>
    #include <osgUtil/SceneView>

    class circleAimlessly : public osg::NodeCallback 
    {
    public:
       circleAimlessly(): _angle(0.0) {}
       virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
       {
          osg::MatrixTransform *tx = dynamic_cast<osg::MatrixTransform *>(node);
          if( tx != NULL )
          {
             _angle += M_PI/180.0;
             tx->setMatrix( osg::Matrix::translate( 100.0, 0.0, 20.0) * 
                osg::Matrix::rotate( _angle, 0, 0, 1 ) );
          }
          traverse(node, nv);
       }
    private:
       float _angle;
    };

    Producer::CameraConfig* setupCameras()
    {
       Producer::CameraConfig* myCameraConfig = new Producer::CameraConfig();
       Producer::Camera* topDownCamera = new Producer::Camera();
       Producer::Camera* mainCamera = new Producer::Camera();

       mainCamera->setProjectionRectangle(0.0f, 1.0f, 0.0f, 1.0f);
       mainCamera->setShareLens(false);
       mainCamera->getLens()->setAutoAspect(true);

       topDownCamera->setProjectionRectangle(0.25f, 0.75f, 0.0f, 0.5f);
       topDownCamera->setShareLens(false);
       topDownCamera->getLens()->setAutoAspect(true);

       myCameraConfig->addCamera("topDownCamera",topDownCamera);
       myCameraConfig->addCamera("mainCamera",mainCamera);

       Producer::RenderSurface* rsOne = mainCamera->getRenderSurface();
       topDownCamera->setRenderSurface( rsOne );
       return myCameraConfig;
    }

    bool setupScene(Producer::ref_ptr<osg::Group> &rootNode,
                    Producer::ref_ptr<osg::Group> &ownTank  )
    {
       if (rootNode.get() || ownTank.get())
          return false;

       osgDB::FilePathList pathList = osgDB::getDataFilePathList();
       pathList.push_back
          ("C:\\Projects\\OpenSceneGraph\\OpenSceneGraph-Data\\NPSData\\Models\\T72-Tank\\");
       pathList.push_back(
          "C:\\Projects\\OpenSceneGraph\\OpenSceneGraph-Data\\NPSData\\Models\\JoeDirt\\");
       osgDB::setDataFilePathList(pathList);

       rootNode = new osg::Group();
       Producer::ref_ptr<osg::Node> terrainNode = 
          osgDB::readNodeFile("JoeDirt.flt");
       if (!terrainNode)
       {
          std::cout << " no terrain! " << std::endl;
          return false;
       }
       rootNode->addChild(terrainNode.get());

       ownTank = (osg::Group*) 
          osgDB::readNodeFile("T72-tank_des.flt");
       if( ! ownTank)
       {
          std::cout << "no Tank" << std::endl;
          return false;
       }

       osg::MatrixTransform * tankXForm = 
          new osg::MatrixTransform();
       tankXForm->setUpdateCallback( new circleAimlessly() );
       rootNode->addChild(tankXForm);
       tankXForm->addChild(ownTank.get());

       osg::Box* unitCube = new osg::Box( osg::Vec3(0,0,0), 20.0f);
       osg::ShapeDrawable* unitCubeDrawable = new osg::ShapeDrawable(unitCube);
       osg::Geode* basicShapesGeode = new osg::Geode();
       basicShapesGeode->addDrawable(unitCubeDrawable);
       tankXForm->addChild(basicShapesGeode);
       basicShapesGeode->setNodeMask(0x2);
       ownTank->setNodeMask(0x1);
       terrainNode->setNodeMask(0x3);

       return true;
    }

    int main()
    {
       Producer::ref_ptr<osg::Group> rootNode; 
       Producer::ref_ptr<osg::Group> tankNode;

       if (!setupScene(rootNode,tankNode))
          return -1;

       Producer::CameraConfig* myCameraConfig = setupCameras();
       osgProducer::Viewer viewer(myCameraConfig);

       viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
       viewer.setSceneData( rootNode.get() );
       viewer.realize();

       int inheritanceMask = 
          (osgUtil::SceneView::VariablesMask::ALL_VARIABLES &
          ~osgUtil::SceneView::VariablesMask::CULL_MASK);

       viewer.getSceneHandlerList().at(0)->getSceneView()->setInheritanceMask(inheritanceMask);
       viewer.getSceneHandlerList().at(0)->getSceneView()->setCullMask(0x1);
       viewer.getSceneHandlerList().at(1)->getSceneView()->setInheritanceMask(inheritanceMask);
       viewer.getSceneHandlerList().at(1)->getSceneView()->setCullMask(0x2);

       osg::Matrixd* topDownViewMatrix = new osg::Matrixd(
          osg::Matrixd::rotate(osg::DegreesToRadians(-90.),1,0,0) *
          osg::Matrixd::translate(0,0,450) );
       topDownViewMatrix->set(
          topDownViewMatrix->inverse(*topDownViewMatrix));
     
       while( !viewer.done() )
       {
          viewer.sync();
          viewer.update();
          viewer.getCameraConfig()->findCamera("topDownCamera")->setViewByMatrix(
             Producer::Matrix(topDownViewMatrix->ptr())  *
             Producer::Matrix::rotate( -M_PI/2.0, 1, 0, 0) );
          viewer.frame();
       }
    }