[osg-users] Multiple Node selection in a rectangular region

161 views
Skip to first unread message

Wuerfel, Hannes

unread,
Oct 20, 2012, 5:16:05 AM10/20/12
to osg-...@lists.openscenegraph.org
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

wh_xiexing

unread,
Oct 20, 2012, 6:27:46 AM10/20/12
to osg-users
  hi friends.   i  look through the code ,but can't  find the places where the osg call opengl's api . like glDrawArray .    
 
could someone tell me how the osg interact with the opengl?
 
Shawl

Wuerfel, Hannes

unread,
Oct 20, 2012, 7:24:11 AM10/20/12
to OpenSceneGraph Users
Well I think my first mistake is in computing the selection bounding box.
Now I use ea.getXnormalized() and ea.getYnormalized() to get normalized window device coordinates.
After that I try to back project the 2D Point into 3D with the following code:

osg::Camera* cam = viewer->getCamera();
osg::Matrix inverseProjection = osg::Matrix::inverse(cam->getProjectionMatrix() * cam->getViewMatrix());

osg::Vec3 inverseProjVectorOld = osg::Vec3(m_X, m_Y, 0.0f) * inverseProjection;
osg::Vec3 inverseProjVectorCurrent = osg::Vec3(currentX, currentY, 0.0f) * inverseProjection;
osg::Vec3 bbMin(inverseProjVectorOld.x(), inverseProjVectorOld.y(), -1000.0f);
osg::Vec3 bbMax(inverseProjVectorCurrent.x(), inverseProjVectorCurrent.y(), 1000.0f);
osg::BoundingBox selectionBox(bbMin, bbMax);

If this right then my selectionBox is a valid bounding box in world space.
But before I can check I think I have to calculate the models bounding box that I want so select in worldspace.

After that I would check
selectionBox.contains(_minBBModel) || selectionBox.contains(_maxBBModel);

It does not seem to work, yet. My SelectionBox coordinates seem strange.
Any suggestions?

Thanks.
________________________________________
Von: osg-user...@lists.openscenegraph.org [osg-user...@lists.openscenegraph.org] im Auftrag von Wuerfel, Hannes
Gesendet: Samstag, 20. Oktober 2012 11:16
An: osg-...@lists.openscenegraph.org
Betreff: [osg-users] Multiple Node selection in a rectangular region

Peterakos

unread,
Oct 20, 2012, 10:01:53 PM10/20/12
to wh_xiexing, OpenSceneGraph Users
Hello.

I assume you have the code of OSG.
Go to svn\OpenSceneGraph\src directory and search all *.cpp files for the gl function you want.

thnx.

Reply all
Reply to author
Forward
0 new messages