Hi all,
I'm currently working my way through the OpenSceneGraph 3.0 Beginner's Guide.
But now I'm stucked with the 'Have a go hero' task in Chapter 9 (selecting 
geometries in a rectangular region).

As proposed I tried to use osgUtil::PolytopeIntersector. But the visitor takes 
too long for me.
So this was my first try.
My root node contains several osgFX::Outline nodes which contain a 3d model 
each.
Is there a trick I'm missing to get it faster since it is widly used 3d 
interaction?

class BadGroupSelectHandler : public osgGA::GUIEventHandler
{
public:
    BadGroupSelectHandler() : m_X(0.0f), m_Y(0.0f) {}

    virtual bool handle(const osgGA::GUIEventAdapter& ea, 
osgGA::GUIActionAdapter& aa)
    {
        if(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) return false;

        switch(ea.getEventType())
        {
            case osgGA::GUIEventAdapter::PUSH:
            case osgGA::GUIEventAdapter::MOVE:
            {
                // record mouse location for the button press and move event
                m_X = ea.getX();
                m_Y = ea.getY();
                return false;
            }
            case osgGA::GUIEventAdapter::RELEASE:
            {
                if(m_X != ea.getX() && m_Y != ea.getY())
                {
                    if(select(ea.getX(), ea.getY(), viewer))
                    {
                        return true;
                    }
                }

                return false;
            }
        }

        return false;
    }

protected:
    bool select(const double currentX, const double currentY, 
osgViewer::Viewer* viewer)
    {
        if(!viewer->getSceneData()) return false;

        float xMin = MIN(m_X, currentX);
        float yMin = MIN(m_Y, currentY);
        float xMax = MAX(m_X, currentX);
        float yMax = MAX(m_Y, currentY);

        osgUtil::PolytopeIntersector* intersector = new 
osgUtil::PolytopeIntersector(osgUtil::PolytopeIntersector::WINDOW,
                                                                                
     xMin, yMin, xMax, yMax);

        osgUtil::IntersectionVisitor iv(intersector);
        viewer->getCamera()->accept(iv); // too slow

        if(intersector->containsIntersections())
        {
                        // if I would iterate over all intersections, i would 
end up with too much intersection data
                        // but I need more than the first intersection
            osgUtil::PolytopeIntersector::Intersection result = 
*(intersector->getIntersections().begin());
            osg::NodePath path = result.nodePath;
                
            for(unsigned int i = 0; i < path.size(); ++i)
            {
                                // do something
            }
            return true;
        }

        return false;
    }

    float m_X;
    float m_Y;
};

My second try was to check against the bounding boxes but I was unable to 
select them:

bool select(const double currentX, const double currentY, osgViewer::Viewer* 
viewer)
{
        osg::Group* root = viewer->getSceneData()->asGroup();
        if(!root) return false;

        double left_, right_, bottom_, top_, near_, far_;
        // I've tried to receive near and far plane
        viewer->getCamera()->getProjectionMatrixAsFrustum(left_, right_, 
bottom_, top_, near_, far_);
        
        // construct selection bounding box
        osg::Vec3 bMin(m_X, m_Y, near_);
        osg::Vec3 bMax(currentX, currentY, far_);
        osg::BoundingBox selectionBox(bMin, bMax);

        for(unsigned int i = 0; i < root->getNumChildren(); ++i)
        {
                osg::BoundingSphere bs = root->getChild(i)->getBound();
                osg::Vec3 _min;
                osg::Vec3 _max;
                _min.set(bs.center().x() - bs.radius(), bs.center().y() - 
bs.radius(), bs.center().z() - bs.radius());
                _max.set(bs.center().x() + bs.radius(), bs.center().y() + 
bs.radius(), bs.center().z() + bs.radius());
                bool intersected = selectionBox.contains(_min) || 
selectionBox.contains(_max);
                if(intersected)
                {
                        // do something
                }
        }
        return false;
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to