[osg-users] Noobie Problem of the Day - Cookbook Surface/Object Picking Not Working

Dave Sargrad davidsargrad at hotmail.com
Mon Apr 13 14:28:04 PDT 2015


I've been working through the osgRecipes cookbooks. I suddenly realized as I was working with cookbook_03_07 that the picking logic did not seem to be working. Indeed I have not been able to pick any of the objects displayed in the cookbooks I've been looking at so far (I'm working the cookbooks in order).

I set a breakpoint in CommonFunctions.cpp within bool PickHandler::handle. I get into the method just fine, when I hold ctrl and left select an object.

However the test intersector ->containsIntersections() always returns false, so a call is never made to doUserOperations.

The only thing that comes to mind is the fact that in my current setup, I have a laptop with 2 external monitors attached, and so the cookbooks render across all 3 of my screens (very nice feature).. I was thinking that perhaps there is something in the cookbook implementation that is ignoring the actual size of my virtual desktop. 

Please forgive the odd looking symbols showing up in the following code blocks... not sure why they are there.

So handle gets called just fine

    bool PickHandler::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::View* viewer = dynamic_cast<osgViewer::View*>(&aa);
        if ( viewer )
            osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector =
                new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, ea.getX(), ea.getY());
            osgUtil::IntersectionVisitor iv( intersector.get() );
            viewer->getCamera()->accept( iv );
            if ( intersector->containsIntersections() ) // <--- Always returns false
                osgUtil::LineSegmentIntersector::Intersection result = *(intersector->getIntersections().begin());
                doUserOperations( result ); 
        return false;

This is the SelectModelHandler class


class SelectModelHandler : public osgCookBook::PickHandler
    SelectModelHandler() : _selector(0) {}
    osg::Geode* createFaceSelector()
        osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(1);
        (*colors)[0] = selectedColor;
        _selector = new osg::Geometry;
        _selector->setDataVariance( osg::Object::DYNAMIC );
        _selector->setUseDisplayList( false );
        _selector->setUseVertexBufferObjects( true );
        _selector->setVertexArray( new osg::Vec3Array(3) );
        _selector->setColorArray( colors.get() );
        _selector->setColorBinding( osg::Geometry::BIND_OVERALL );
        _selector->addPrimitiveSet( new osg::DrawArrays(GL_TRIANGLES, 0, 3) );
        osg::ref_ptr<osg::Geode> geode = new osg::Geode;
        geode->addDrawable( _selector.get() );
        geode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
        geode->getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
        geode->getOrCreateStateSet()->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
        return geode.release();
    virtual void doUserOperations( osgUtil::LineSegmentIntersector::Intersection& result )
        osg::Geometry* geom = dynamic_cast<osg::Geometry*>( result.drawable.get() );
        if ( !geom || !_selector || geom==_selector ) return;
        osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>( geom->getVertexArray() );
        osg::Vec3Array* selVertices = dynamic_cast<osg::Vec3Array*>( _selector->getVertexArray() );
        if ( !vertices || !selVertices ) return;
        osg::Matrix matrix = osg::computeLocalToWorld( result.nodePath );
        const std::vector<unsigned int>& selIndices = result.indexList;
        for ( unsigned int i=0; i<3 && i<selIndices.size(); ++i )
            unsigned int pos = selIndices[i];
            (*selVertices)[i] = (*vertices)[pos] * matrix;
    osg::ref_ptr<osg::Geometry> _selector;

The main method attaches the selector as a child


int main( int argc, char** argv )
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable( createSimpleGeometry() );
    geode->getOrCreateStateSet()->setAttributeAndModes( new osg::PolygonOffset(1.0f, 1.0f) );
    osg::ref_ptr<osg::MatrixTransform> trans = new osg::MatrixTransform;
    trans->addChild( geode.get() );
    trans->setMatrix( osg::Matrix::translate(0.0f, 0.0f, 1.0f) );
    osg::ref_ptr<SelectModelHandler> selector = new SelectModelHandler;
    osg::ref_ptr<osg::Group> root = new osg::Group;
    root->addChild( trans.get() );
    root->addChild( selector->createFaceSelector() );  // Caution: It has bound, too
    osgViewer::Viewer viewer;
    viewer.addEventHandler( selector.get() );
    viewer.setSceneData( root.get() );
    return viewer.run();

Does anyone see something that would cause this PickHandler not to work when used on a 3 monitor setup? 

Thank you!


Read this topic online here:

More information about the osg-users mailing list