Hi,

I would like to know if other found some strange issue with multi threaded, and render slave camera to fbo. Here what i do. In order to get screenshoot of top view and front view of a scene, i added two slave camera (AbsoluteRF) and share the same graphiccontext. I start from the osgprerender camera intialisation with some adjustement. The issue is it works for the first slave camera, but not the second (if i called twice the function i get a correct screenshoot), so it looks like a synchronisation issue or something like that. I know it's secure to make modification in the scene graph during in the update traversal. So during the traversal i add an postdrawcallback to the two slave camerao that will just save the result of the image rendered (respective to each camera) to the disk and then the callback is removed. When i force the setThreadingModel(osgViewer::Viewer::SingleThreaded); everything works as it should be, so I imagine i missed something on thread synchronisation. I thought making things in the traversal update was good. I tried different thread model to try to understand, in SingleThreaded and CullDrawThreadPerContext it works, but DrawThreadPerContext and CullThreadPerCameraDrawThreadPerContext works for the first slave camera. Just for informations i have a dual core with nvidia system on linux.
I use osg 2.4 and i have the same issue with the last svn version 2.5.3

Any clue ?

void MyClass::addScreenShootCamera(osgViewer::Viewer* viewer, osg::NodeCallback* callback, const osg::Matrix& view, const std::string& filename)
{
  int tex_width = 300;
  int tex_height = 200;
  osg::ref_ptr<osg::Camera> camera = new osg::Camera;
  // set up the background color and clear mask.
  camera->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f));
  camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  // set viewport
  camera->setGraphicsContext(viewer->getCamera()->getGraphicsContext());
  camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
  camera->setViewport(0,0,tex_width,tex_height);
  double ratio = tex_height * 1.0 /tex_width;
  camera->setProjectionMatrixAsOrtho(-1, 1,-ratio, ratio, -10000, 10000);
  camera->setViewMatrix(view);

osg::Camera::RenderTargetImplementation renderImplementation = osg::Camera::FRAME_BUFFER_OBJECT;
  camera->setRenderTargetImplementation(renderImplementation);
  osg::Image* image = new osg::Image;
image->allocateImage(tex_width, tex_height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
  image->setFileName(filename);
  // attach the image so its copied on each frame.
  camera->attach(osg::Camera::COLOR_BUFFER, image);
//   camera->setDataVariance(osg::Object::DYNAMIC);
  viewer->addSlave(camera.get());
AdaptProjectionForSceneSizeForFrontView* callback_casted = dynamic_cast<AdaptProjectionForSceneSizeForFrontView*>(callback);
  callback_casted->useImage(image);
  callback_casted->setCamera(camera.get());
  camera->setUpdateCallback(callback);
}

any clue ?

// boring code
struct AdaptProjectionForSceneSizeForFrontView : public osg::NodeCallback
{
 osg::ref_ptr<osgViewer::Viewer> _viewer;
 bool _needUpdate;
 osg::ref_ptr<osg::Image> _image;
 osg::ref_ptr<osg::Camera> _camera;
AdaptProjectionForSceneSizeForFrontView(osgViewer::Viewer* viewer) : _viewer(viewer), _needUpdate (true) {}
 void useImage(osg::Image* image) { _image = image; }
 void setCamera(osg::Camera* camera) { _camera = camera;}
 void needUpdate(bool state) { _needUpdate = state; }
virtual void updateProjection(osg::Camera* cam, const osg::BoundingBox& sceneSize)
 {
   double ratio = _image->t() * 1.0/ _image->s();
   float width = sceneSize._max[0] - sceneSize._min[0];
   float height = sceneSize._max[2] - sceneSize._min[2];
   if (height > width * ratio)
     width = height / ratio;
   height = width * ratio;
width *= 0.5;
   height *= 0.5;
   std::cout << "front" << std::endl;
std::cout << -width + sceneSize.center()[0] << " " << width + sceneSize.center()[0] << " " << -height + sceneSize.center()[2] << " " << height + sceneSize.center()[2] << std::endl;
   cam->setProjectionMatrixAsOrtho(-width + sceneSize.center()[0],
                                   width + sceneSize.center()[0],
                                   -height + sceneSize.center()[2],
                                   height + sceneSize.center()[2],
                                   -10000,
                                   10000);
 }
 void operator()(osg::Node* node, osg::NodeVisitor* nv) {
if (_needUpdate && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR && _viewer->getSceneData()) {
     osg::BoundingBox sceneSize;
osg::ref_ptr<osg::ComputeBoundsVisitor> bb = new osg::ComputeBoundsVisitor;
     _viewer->getSceneData()->accept(*bb);
     sceneSize = bb->getBoundingBox();
     osg::Camera* cam = dynamic_cast<osg::Camera*>(node);
     if (cam) {
std::cout << "Scene size " << bb->getBoundingBox()._min << " " << bb->getBoundingBox()._max << std::endl;
       updateProjection(cam, sceneSize);
       _camera->setPostDrawCallback(new PSDrawCallback(_image.get()));
       _needUpdate = false;
     }
   }
   traverse(node,nv);
 }
};

and the postdrawcallback core

void PSDrawCallback::operator () (osg::RenderInfo& renderInfo) const
{
 osg::Camera* camera = renderInfo.getCurrentCamera();
 osgDB::writeImageFile(*_image, _image->getFileName());
 camera->setPostDrawCallback(0); // delete the callback
}

--
+33 (0) 6 63 20 03 56  Cedric Pinson mailto:[EMAIL PROTECTED] 
http://www.plopbyte.net


_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to