Hi Simon,

Yes, he wants to only pick objects which are pickable AND visible.
Which you can't do just using a node mask, you'll get anything which is
pickable OR visible.

That's a bug IMHO. If I say this:

int VISIBLE_MASK = 0x01;
int PICKABLE_MASK = 0x02;

// Render only what's visible
view->getCamera()->setCullMask(VISIBLE_MASK);

// Pick what's visible and pickable
intersectionVisitor->setTraversalMask(VISIBLE_MASK | PICKABLE_MASK);

visibleNode->setNodeMask(VISIBLE_MASK);
pickableVisibleNode->setNodeMask(VISIBLE_MASK | PICKABLE_MASK);
pickableNode->setNodeMask(PICKABLE_MASK);

Then I should only see the nodes that have VISIBLE_MASK set (so visibleNode and pickableVisibleNode above), and I should only be able to pick nodes that have both VISIBLE_MASK and PICKABLE_MASK set (so only pickableVisibleNode above). The rendering works (I only see visibleNode and pickableVisibleNode) but the picking sees all three nodes.

Here's a modified osgpick that shows this. In the 5 boxes on the left side of the window, the first is VISIBLE but not PICKABLE, the second is both, the third is PICKABLE but not VISIBLE, and the last two are both. Indeed we don't see the third, so that's fine, but we can still pick all 5.

Instead of (traversalMask & nodeMask) != 0, perhaps the condition should be (traversalMask & nodeMask) == traversalMask... Or perhaps there's a rationale for being able to pick whatever has part of the traversal mask, but not the mask exactly, but I can't see it right now...

I can't delve into this at present, but with an example that shows the problem perhaps others can fix it...

J-S
--
______________________________________________________
Jean-Sebastien Guay    [email protected]
                               http://www.cm-labs.com/
                        http://whitestar02.webhop.org/
/* OpenSceneGraph example, osgpick.
*
*  Permission is hereby granted, free of charge, to any person obtaining a copy
*  of this software and associated documentation files (the "Software"), to deal
*  in the Software without restriction, including without limitation the rights
*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the Software is
*  furnished to do so, subject to the following conditions:
*
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
*  THE SOFTWARE.
*/

/* osgpick sample
* demonstrate use of osgUtil/PickVisitor for picking in a HUD or
* in a 3d scene,
*/

#include <osgUtil/Optimizer>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osgViewer/CompositeViewer>

#include <osgGA/TerrainManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>

#include <osg/Material>
#include <osg/Geode>
#include <osg/BlendFunc>
#include <osg/Depth>
#include <osg/Projection>
#include <osg/MatrixTransform>
#include <osg/Camera>
#include <osg/io_utils>
#include <osg/ShapeDrawable>

#include <osgText/Text>

#include <sstream>

int VISIBLE_MASK = 0x01;
int PICKABLE_MASK = 0x02;

// class to handle events with a pick
class PickHandler : public osgGA::GUIEventHandler {
public: 

    PickHandler(osgText::Text* updateText):
        _updateText(updateText) {}
        
    ~PickHandler() {}
    
    bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa);

    virtual void pick(osgViewer::View* view, const osgGA::GUIEventAdapter& ea);

    void setLabel(const std::string& name)
    {
        if (_updateText.get()) _updateText->setText(name);
    }
    
protected:

    osg::ref_ptr<osgText::Text>  _updateText;
};

bool PickHandler::handle(const osgGA::GUIEventAdapter& 
ea,osgGA::GUIActionAdapter& aa)
{
    switch(ea.getEventType())
    {
        case(osgGA::GUIEventAdapter::PUSH):
        {
            osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
            if (view) pick(view,ea);
            return false;
        }    
        case(osgGA::GUIEventAdapter::KEYDOWN):
        {
            if (ea.getKey()=='c')
            {        
                osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
                osg::ref_ptr<osgGA::GUIEventAdapter> event = new 
osgGA::GUIEventAdapter(ea);
                event->setX((ea.getXmin()+ea.getXmax())*0.5);
                event->setY((ea.getYmin()+ea.getYmax())*0.5);
                if (view) pick(view,*event);
            }
            return false;
        }    
        default:
            return false;
    }
}

void PickHandler::pick(osgViewer::View* view, const osgGA::GUIEventAdapter& ea)
{
    osgUtil::LineSegmentIntersector::Intersections intersections;

    std::string gdlist="";
    float x = ea.getX();
    float y = ea.getY();
#if 0
    osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new 
osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x, y);
    osgUtil::IntersectionVisitor iv(picker.get());
    view->getCamera()->accept(iv);
    if (picker->containsIntersections())
    {
        intersections = picker->getIntersections();
#else
    if (view->computeIntersections(x,y,intersections, 
VISIBLE_MASK|PICKABLE_MASK))
    {
#endif
        for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = 
intersections.begin();
            hitr != intersections.end();
            ++hitr)
        {
            std::ostringstream os;
            if (!hitr->nodePath.empty() && 
!(hitr->nodePath.back()->getName().empty()))
            {
                // the geodes are identified by name.
                os<<"Object 
\""<<hitr->nodePath.back()->getName()<<"\""<<std::endl;
            }
            else if (hitr->drawable.valid())
            {
                os<<"Object \""<<hitr->drawable->className()<<"\""<<std::endl;
            }

            os<<"        local coords vertex("<< 
hitr->getLocalIntersectPoint()<<")"<<"  
normal("<<hitr->getLocalIntersectNormal()<<")"<<std::endl;
            os<<"        world coords vertex("<< 
hitr->getWorldIntersectPoint()<<")"<<"  
normal("<<hitr->getWorldIntersectNormal()<<")"<<std::endl;
            const osgUtil::LineSegmentIntersector::Intersection::IndexList& vil 
= hitr->indexList;
            for(unsigned int i=0;i<vil.size();++i)
            {
                os<<"        vertex indices ["<<i<<"] = "<<vil[i]<<std::endl;
            }
            
            gdlist += os.str();
        }
    }
    setLabel(gdlist);
}

osg::Node* createHUD(osgText::Text* updateText)
{

    // create the hud. derived from osgHud.cpp
    // adds a set of quads, each in a separate Geode - which can be picked 
individually
    // eg to be used as a menuing/help system!
    // Can pick texts too!

    osg::Camera* hudCamera = new osg::Camera;
    hudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
    hudCamera->setProjectionMatrixAsOrtho2D(0,1280,0,1024);
    hudCamera->setViewMatrix(osg::Matrix::identity());
    hudCamera->setRenderOrder(osg::Camera::POST_RENDER);
    hudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);
    
    std::string timesFont("fonts/times.ttf");
    
    // turn lighting off for the text and disable depth test to ensure its 
always ontop.
    osg::Vec3 position(150.0f,800.0f,0.0f);
    osg::Vec3 delta(0.0f,-60.0f,0.0f);
    
    {
        osg::Geode* geode = new osg::Geode();
        osg::StateSet* stateset = geode->getOrCreateStateSet();
        stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
        stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
        geode->setName("simple");
        hudCamera->addChild(geode);
        
        osgText::Text* text = new  osgText::Text;
        geode->addDrawable( text );
        
        text->setFont(timesFont);
        text->setText("Picking in Head Up Displays is simple!");
        text->setPosition(position);
        
        position += delta;
    }    
    
    
    for (int i=0; i<5; i++) {
        osg::Vec3 dy(0.0f,-30.0f,0.0f);
        osg::Vec3 dx(120.0f,0.0f,0.0f);
        osg::Geode* geode = new osg::Geode();
        osg::StateSet* stateset = geode->getOrCreateStateSet();
        const char *opts[]={"One", "Two", "Three", "January", "Feb", "2003"};
        osg::Geometry *quad=new osg::Geometry;
        stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
        stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
        std::string name="subOption";
        name += " ";
        name += std::string(opts[i]);
        geode->setName(name);
        osg::Vec3Array* vertices = new osg::Vec3Array(4); // 1 quad
        osg::Vec4Array* colors = new osg::Vec4Array;
        colors = new osg::Vec4Array;
        colors->push_back(osg::Vec4(0.8-0.1*i,0.1*i,0.2*i, 1.0));
        quad->setColorArray(colors);
        quad->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);
        (*vertices)[0]=position;
        (*vertices)[1]=position+dx;
        (*vertices)[2]=position+dx+dy;
        (*vertices)[3]=position+dy;
        quad->setVertexArray(vertices);
        quad->addPrimitiveSet(new 
osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
        geode->addDrawable(quad);
        hudCamera->addChild(geode);

        if (i == 0) geode->setNodeMask(VISIBLE_MASK);
        if (i == 1) geode->setNodeMask(VISIBLE_MASK|PICKABLE_MASK);
        if (i == 2) geode->setNodeMask(PICKABLE_MASK);
        if (i == 3) geode->setNodeMask(VISIBLE_MASK|PICKABLE_MASK);
        if (i == 4) geode->setNodeMask(VISIBLE_MASK|PICKABLE_MASK);
        
        position += delta;
    }    
    
    
    
    { // this displays what has been selected
        osg::Geode* geode = new osg::Geode();
        osg::StateSet* stateset = geode->getOrCreateStateSet();
        stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
        stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
        geode->setName("The text label");
        geode->addDrawable( updateText );
        hudCamera->addChild(geode);
        
        updateText->setCharacterSize(20.0f);
        updateText->setFont(timesFont);
        updateText->setColor(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
        updateText->setText("");
        updateText->setPosition(position);
        updateText->setDataVariance(osg::Object::DYNAMIC);
        
        position += delta;
    }    
    
    return hudCamera;

}

int main( int argc, char **argv )
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // read the scene from the list of file specified commandline args.
    osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);

    if (!scene && arguments.read("--relative-camera-scene"))
    {
        // Create a test scene with a camera that has a relative reference 
frame.
        osg::Group* group = new osg::Group();

        osg::Geode* sphere = new osg::Geode();
        sphere->setName("Sphere");
        sphere->addDrawable(new osg::ShapeDrawable(new osg::Sphere()));

        osg::Geode* cube = new osg::Geode();
        cube->setName("Cube");
        cube->addDrawable(new osg::ShapeDrawable(new osg::Box()));

        osg::Camera* camera = new osg::Camera();
        camera->setRenderOrder(osg::Camera::POST_RENDER);
        camera->setClearMask(GL_DEPTH_BUFFER_BIT);
        camera->setReferenceFrame(osg::Transform::RELATIVE_RF);
        camera->setViewMatrix(osg::Matrix::translate(-2, 0, 0));

        osg::MatrixTransform* xform = new 
osg::MatrixTransform(osg::Matrix::translate(1, 1, 1));
        xform->addChild(camera);

        group->addChild(sphere);
        group->addChild(xform);
        camera->addChild(cube);

        scene = group;
    }

    // if not loaded assume no arguments passed in, try use default mode 
instead.
    if (!scene) scene = osgDB::readNodeFile("fountain.osg");

    osg::ref_ptr<osg::Group> group = dynamic_cast<osg::Group*>(scene.get());
    if (!group)
    {
        group = new osg::Group;
        group->addChild(scene.get());
    }

    osg::ref_ptr<osgText::Text> updateText = new osgText::Text;

    // add the HUD subgraph.    
    group->addChild(createHUD(updateText.get()));

    if (arguments.read("--CompositeViewer"))
    {
        osg::ref_ptr<osgViewer::View> view = new osgViewer::View;
        // add the handler for doing the picking
        view->addEventHandler(new PickHandler(updateText.get()));

        // set the scene to render
        view->setSceneData(group.get());

        view->setUpViewAcrossAllScreens();

        osgViewer::CompositeViewer viewer;
        viewer.addView(view.get());

        return viewer.run();

    }
    else
    {
        osgViewer::Viewer viewer;


        // add all the camera manipulators
        {
            osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> 
keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;

            keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new 
osgGA::TrackballManipulator() );
            keyswitchManipulator->addMatrixManipulator( '2', "Flight", new 
osgGA::FlightManipulator() );
            keyswitchManipulator->addMatrixManipulator( '3', "Drive", new 
osgGA::DriveManipulator() );

            unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
            keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new 
osgGA::TerrainManipulator() );

            std::string pathfile;
            char keyForAnimationPath = '5';
            while (arguments.read("-p",pathfile))
            {
                osgGA::AnimationPathManipulator* apm = new 
osgGA::AnimationPathManipulator(pathfile);
                if (apm || !apm->valid()) 
                {
                    num = keyswitchManipulator->getNumMatrixManipulators();
                    keyswitchManipulator->addMatrixManipulator( 
keyForAnimationPath, "Path", apm );
                    ++keyForAnimationPath;
                }
            }

            keyswitchManipulator->selectMatrixManipulator(num);

            viewer.setCameraManipulator( keyswitchManipulator.get() );
        }

        // add the handler for doing the picking
        viewer.addEventHandler(new PickHandler(updateText.get()));

        // set the scene to render
        viewer.setSceneData(group.get());

        viewer.getCamera()->setCullMask(VISIBLE_MASK);

        viewer.setUpViewInWindow(50, 50, 1024, 768);
    
        return viewer.run();
    }

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

Reply via email to