Search code examples
openglrenderingopenscenegraph

How to change background at runtime on openscenegraph


I try to add an 3d object on viewer and change background dynamically. I capture webcam using opencv VideoCapture.

I did below steps :

  1. Open video capture and get frame

  2. Create openscenegraph root

  3. Add a child to root ( read from .osg file 3d object)

  4. Create a texture2d object for background

  5. Set image of background

  6. Create a camera to view background

  7. Add camera to root

  8. Set data of viewer (viewer.setScenedat(root))

  9. Run viewer.run()

    These steps add first frame as background and add a 3d object to scene. But I can't change background each frame. How can I do it?

Code :

cv::VideoCapture cap(0);  
cv::Mat frame;

if(!cap.isOpened())  
{
    std::cout << "Webcam cannot open!\n";
    return;
}  

osgViewer::Viewer viewer;
osg::ref_ptr<osg::Group> root = new osg::Group();
osg::ref_ptr<osg::Texture2D> bg = new osg::Texture2D();

root->addChild(osgDB::readNodeFile("object.osg"));
bg->setFilter(osg::Texture::FilterParameter::MIN_FILTER, osg::Texture::FilterMode::LINEAR);
bg->setFilter(osg::Texture::FilterParameter::MAG_FILTER, osg::Texture::FilterMode::LINEAR);    
bg->setDataVariance(osg::Object::DYNAMIC);

cap >> frame;
osg::ref_ptr<osg::Image> osgImage = new osg::Image;
osgImage->setImage(frame.cols, frame.rows, 3,
    GL_RGB, GL_RGB, GL_UNSIGNED_BYTE,
    (uchar*)(frame.data),
    osg::Image::AllocationMode::NO_DELETE, 1);
bg->setImage(osgImage);

osg::ref_ptr<osg::Camera> bg_cam = new osg::Camera();
bg_cam->setProjectionMatrixAsOrtho2D(-0.5, 0.5, -0.5, 0.5);
bg_cam->setViewMatrixAsLookAt(
    osg::Vec3(0.5, 0.5, -1.0),
    osg::Vec3(0.5, 0.5, 0.0),
    osg::Vec3(0.0, -1.0, 0.0)
    );
bg_cam->setRenderOrder(osg::Camera::PRE_RENDER);
bg_cam->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
bg_cam->addChild(initializeBackground(bg));
root->addChild(bg_cam);

viewer.setSceneData(root);
viewer.getCamera()->setProjectionMatrixAsPerspective(
    40., 1., 1., 100.);
viewer.getCamera()->setClearMask(GL_DEPTH_BUFFER_BIT);
viewer.getCamera()->setClearColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));
  
viewer.run();

Solution

  • viewer.getCamera()->setClearMask(GL_DEPTH_BUFFER_BIT);
    viewer.getCamera()->setClearColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));
     bg->setDataVariance(osg::Object::DYNAMIC);
    viewer.realize();  // set up windows and associated threads. 
    
    while(!viewer.done())
    {
        cap >> frame;     
    
        osg::ref_ptr<osg::Image> osgImage = new osg::Image;
        osgImage->setImage(frame.cols, frame.rows, 3,
            GL_RGB, GL_BGR, GL_UNSIGNED_BYTE,
            (uchar*)(frame.data),
            osg::Image::AllocationMode::NO_DELETE, 1);
        bg->setImage(osgImage);
    
        viewer.frame();
    }   
    

    This code changes background dynamially.