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