Now, a conclusion on this thread: here is how I solved that issue: I'm "registering" all the cameras where I have contain to intersect with, and then I take them one by one to perform an intersection test, but you need to modify the view amtrix, projection matrix and viewport (using those from the main camera), and then I use a modified IntersectionVisitor to "correct" the projection matrix before entering a camera. So here it the most important code parts if someone is interested in introducing that in the core OSG libs one day (sorry I'm really late on my job, so I don't have time for a submission right now :-( ).
main function to do some intersection tests:
bool Tools::handleViewIntersections(osgViewer::View * view, double x, double y)
{
// Bouml preserved body begin 00043B04
if(!view) {
vLog::logError("invalid view object in tools::handleViewIntersections()");
return false;
}
osgUtil::LineSegmentIntersector::Intersections hits;
float local_x, local_y = 0.0;
view->getCameraContainingPosition(x, y, local_x, local_y);
osg::Camera* camera = view->getCamera();
osg::Matrixd pm,vm;
osg::ref_ptr<osg::Viewport> vp;
osgUtil::LineSegmentIntersector::CoordinateFrame cf = camera->getViewport() ? osgUtil::Intersector::WINDOW : osgUtil::Intersector::PROJECTION;
osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new osgUtil::LineSegmentIntersector(cf, local_x, local_y);
vDisplay::DisplayManager::CameraDeq& cams = vDisplay::DisplayManager::getRegisteredCameras(view);
for(vDisplay::DisplayManager::CameraDeq::iterator it = cams.begin(); it != cams.end(); ++it) {
//osgUtil::IntersectionVisitor iv(picker.get());
vOGL::ExtendedIntersectionVisitor iv(picker.get());
iv.setFrameStamp(vDisplay::DisplayManager::getViewer()->getFrameStamp());
iv.setTraversalMask(vOGL::PICKABLE);
vm = (*it)->getViewMatrix();
pm = (*it)->getProjectionMatrix();
vp = (*it)->getViewport();
(*it)->setViewMatrix(camera->getViewMatrix());
(*it)->setProjectionMatrix(camera->getProjectionMatrix());
(*it)->setViewport(camera->getViewport());
(*it)->accept(iv);
(*it)->setViewMatrix(vm);
(*it)->setProjectionMatrix(pm);
(*it)->setViewport(vp.get());
if (picker->containsIntersections())
{
hits = picker->getIntersections();
vLog::logInfo("Got %d intersections",hits.size());
return true;
}
}
vLog::logInfo("Got 0 intersections");
return false;
// Bouml preserved body end 00043B04
}
the modified function in my ExtendedIntersectionVisitor:
void ExtendedIntersectionVisitor::apply(osg::Camera & camera) {
// Bouml preserved body begin 00043C84
// Use a simplified cull traversal here to correct the projection:
osg::RenderInfo _renderInfo;
_renderInfo.setState(new osg::State);
_renderInfo.setView(camera.getView());
osg::ref_ptr<osgUtil::CullVisitor> cv = osgUtil::CullVisitor::create();
cv->setTraversalMask(getTraversalMask()); // Use the same mask to retrieve the good extend of the pickable objects.
osg::ref_ptr<osgUtil::RenderStage> renderStage = new osgUtil::RenderStage();
osg::ref_ptr<osgUtil::StateGraph> rendergraph = new osgUtil::StateGraph();
cv->setStateGraph(rendergraph.get());
cv->setRenderStage(renderStage.get());
cv->reset();
cv->setFrameStamp(const_cast<osg::FrameStamp*>(getFrameStamp()));
if (getFrameStamp())
{
cv->setTraversalNumber(getFrameStamp()->getFrameNumber());
}
//cv->inheritCullSettings(*this);
cv->setClearNode(NULL); // reset earth sky on each frame.
cv->setStateGraph(rendergraph.get());
cv->setRenderStage(renderStage.get());
cv->setRenderInfo( _renderInfo );
renderStage->reset();
rendergraph->clean();
renderStage->setViewport(camera.getViewport());
renderStage->setClearColor(camera.getClearColor());
renderStage->setClearMask(camera.getClearMask());
renderStage->setCamera(&camera);
cv->pushViewport(camera.getViewport());
cv->pushProjectionMatrix(new osg::RefMatrix(camera.getProjectionMatrix()));
cv->pushModelViewMatrix(new osg::RefMatrix(camera.getViewMatrix()),osg::Transform::ABSOLUTE_RF);
for(unsigned int childNo=0;
childNo<camera.getNumChildren();
++childNo)
{
camera.getChild(childNo)->accept(*cv);
}
cv->popModelViewMatrix();
cv->popProjectionMatrix();
cv->popViewport();
renderStage->sort();
rendergraph->prune();
// Projection correction:
osg::Matrixd proj = camera.getProjectionMatrix();
osgUtil::CullVisitor::value_type zNear = cv->getCalculatedNearPlane();
osgUtil::CullVisitor::value_type zFar = cv->getCalculatedFarPlane();
cv->clampProjectionMatrix(proj,zNear,zFar);
// Normal process:
if (camera.getViewport()) pushWindowMatrix( camera.getViewport() );
pushProjectionMatrix( new osg::RefMatrix(proj) );
pushViewMatrix( new osg::RefMatrix(camera.getViewMatrix()) );
pushModelMatrix( new osg::RefMatrix() );
// now push an new intersector clone transform to the new local coordinates
push_clone();
traverse(camera);
// pop the clone.
pop_clone();
popModelMatrix();
popViewMatrix();
popProjectionMatrix();
if (camera.getViewport()) popWindowMatrix();
// Bouml preserved body end 00043C84}... I'm not sure we need to setup the CullVisitor so much : but I just took most of the implementation from SceneView::cullstate(...) and it's working like that... and as I said, I'm in an hurry now :-)
regards,
Manu.