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
osg-...@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org