Hi all,
I just met a not too small nor too big problem while working on an
earth simulation application. Because we have to look closely at some
detailed objects (like a car in Beijing), I have an idea of ignoring
earth vertices while automatically computing near/far planes in those
cases, which will make the near/far planes suitable for viewing
specified nodes and free me from adjusting near/far ratio all the
time. To achieve this, I put the earth model under a nested camera and
set DO_NOT_COMPUTE_NEAR_FAR:
osg::ref_ptr<osg::Camera> earthCamera = new osg::Camera;
earthCamera->setRenderOrder( osg::Camera::NESTED_RENDER );
earthCamera->setComputeNearFarMode( osg::Camera::DO_NOT_COMPUTE_NEAR_FAR );
earthCamera->addChild( earthModel.get() );
root->addChild( earthCamera.get() );
root->addChild( otherModelsOnEarth );
This works for me, but I found another problem that the intersection
calculating is incorrect. As the file attached shows, I made a pick
handler to pick the earth model (CTRL + left button) and print a
message on the console, but it never worked if the earth's parent is a
nested camera, while working correctly if its parent is a normal group
node.
After a long time debug, I found that the problem happened because the
near/far computing results is not set to any scene cameras. The
computed near/far values are only recorded in the projection stack for
correct rendering, but neither in the viewer's main camera nor nested
camera node, and thus led to wrong MVPW matrix in the intersection
visitor.
Without disturbed by nested camera nodes, the two values will be set
back to the main camera in the SceneView::cull() function, and
everything could continue to work. That means, objects under camera
nodes in the scene graph may not be correctly picked with
IntersectionVisitor, because of the missed near/far planes.
Any ideas or suggestions about this issue?
Cheers,
Wang Rui
#include <osg/Texture2D>
#include <osg/ShapeDrawable>
#include <osgDB/FileUtils>
#include <osgDB/ReadFile>
#include <osgUtil/LineSegmentIntersector>
#include <osgViewer/Viewer>
osg::Geode* createEarth( const osg::Vec3d& center )
{
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable( new osg::ShapeDrawable(new osg::Sphere(center, osg::WGS_84_RADIUS_POLAR)) );
std::string filename = osgDB::findDataFile( "Images/land_shallow_topo_2048.jpg" );
geode->getOrCreateStateSet()->setTextureAttributeAndModes( 0, new osg::Texture2D(osgDB::readImageFile(filename)) );
return geode.release();
}
class PickHandler : public osgGA::GUIEventHandler
{
public:
virtual bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
{
if ( ea.getEventType()!=osgGA::GUIEventAdapter::RELEASE ||
ea.getButton()!=osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON ||
!(ea.getModKeyMask()&osgGA::GUIEventAdapter::MODKEY_CTRL) )
return false;
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
if ( viewer )
{
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector = new osgUtil::LineSegmentIntersector(
osgUtil::Intersector::PROJECTION, ea.getXnormalized(), ea.getYnormalized());
osgUtil::IntersectionVisitor iv( intersector.get() );
viewer->getCamera()->accept( iv );
if ( intersector->containsIntersections() )
std::cout << "We have picked a model!" << std::endl;
}
return false;
}
};
int main( int argc, char** argv )
{
osg::ref_ptr<osg::Node> model = createEarth( osg::Vec3() );
//osg::ref_ptr<osg::Group> modelCamera = new osg::Group;
osg::ref_ptr<osg::Camera> modelCamera = new osg::Camera;
modelCamera->setRenderOrder( osg::Camera::NESTED_RENDER );
modelCamera->addChild( model.get() );
osg::ref_ptr<osg::Group> root = new osg::Group;
root->addChild( modelCamera.get() );
osgViewer::Viewer viewer;
viewer.setSceneData( root.get() );
viewer.addEventHandler( new PickHandler );
viewer.setUpViewInWindow( 100, 100, 800, 600 );
return viewer.run();
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org