Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes needed for envire #31

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
321 changes: 138 additions & 183 deletions src/PickHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ using namespace vizkit3d;

PickHandler::PickHandler():
_mx(0.0),_my(0.0),
_usePolytopeIntersector(false),
_useWindowCoordinates(false) {}
_usePolytopeIntersector(true) {}

PickHandler::~PickHandler() {}

Expand Down Expand Up @@ -67,94 +66,84 @@ bool PickHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapt
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::KEYDOWN):
{
if (ea.getKey()=='w')
{
if (ea.getKey()=='w')
{
this->wireFrameModeOn(viewer->getSceneData());
}
else if (ea.getKey()=='n')
{
this->wireFrameModeOff(viewer->getSceneData());
}
else
{
keyFunctionMap::iterator itr = keyFuncMap.find(ea.getKey());
if (itr != keyFuncMap.end())
{
if ( (*itr).second.keyState == KEY_UP )
{
(*itr).second.keyState = KEY_DOWN;
newKeyDownEvent = true;
}
if (newKeyDownEvent)
{
(*itr).second.keyFunction();
newKeyDownEvent = false;
}
return true;
}
}
return false;
this->wireFrameModeOn(viewer->getSceneData());
}
case(osgGA::GUIEventAdapter::KEYUP):
{
if (ea.getKey()=='p')
{
_usePolytopeIntersector = !_usePolytopeIntersector;
if (_usePolytopeIntersector)
{
osg::notify(osg::NOTICE)<<"Using PolytopeIntersector"<<std::endl;
} else {
osg::notify(osg::NOTICE)<<"Using LineSegmentIntersector"<<std::endl;
}
}
else if (ea.getKey()=='c')
{
_useWindowCoordinates = !_useWindowCoordinates;
if (_useWindowCoordinates)
{
osg::notify(osg::NOTICE)<<"Using window coordinates for picking"<<std::endl;
} else {
osg::notify(osg::NOTICE)<<"Using projection coordiates for picking"<<std::endl;
}
}
else
else if (ea.getKey()=='n')
{
this->wireFrameModeOff(viewer->getSceneData());
}
else
{
keyFunctionMap::iterator itr = keyFuncMap.find(ea.getKey());
if (itr != keyFuncMap.end())
{
keyFunctionMap::iterator itr = keyFuncMap.find(ea.getKey());
if (itr != keyFuncMap.end() )
if ( (*itr).second.keyState == KEY_UP )
{
(*itr).second.keyState = KEY_UP;
(*itr).second.keyState = KEY_DOWN;
newKeyDownEvent = true;
}

itr = keyUPFuncMap.find(ea.getKey());
if (itr != keyUPFuncMap.end())
if (newKeyDownEvent)
{
(*itr).second.keyFunction();
return true;
newKeyDownEvent = false;
}
return true;
}
}
return false;
}
case(osgGA::GUIEventAdapter::KEYUP):
{
if (ea.getKey()=='p')
{
_usePolytopeIntersector = !_usePolytopeIntersector;
if (_usePolytopeIntersector)
{
osg::notify(osg::NOTICE)<<"Using PolytopeIntersector"<<std::endl;
} else {
osg::notify(osg::NOTICE)<<"Using LineSegmentIntersector"<<std::endl;
}
}
else
{
keyFunctionMap::iterator itr = keyFuncMap.find(ea.getKey());
if (itr != keyFuncMap.end() )
{
(*itr).second.keyState = KEY_UP;
}

return false;
}
case(osgGA::GUIEventAdapter::PUSH):
case(osgGA::GUIEventAdapter::MOVE):
{
_mx = ea.getX();
_my = ea.getY();
return false;
}
case(osgGA::GUIEventAdapter::RELEASE):
{
if (_mx == ea.getX() && _my == ea.getY())
{
// only do a pick if the mouse hasn't moved
pick(ea,viewer);
}
return false;
itr = keyUPFuncMap.find(ea.getKey());
if (itr != keyUPFuncMap.end())
{
(*itr).second.keyFunction();
return true;
}
}

return false;
}
case(osgGA::GUIEventAdapter::PUSH):
case(osgGA::GUIEventAdapter::MOVE):
{
_mx = ea.getX();
_my = ea.getY();
return false;
}
case(osgGA::GUIEventAdapter::RELEASE):
{
if (_mx == ea.getX() && _my == ea.getY())
{
// only do a pick if the mouse hasn't moved
pick(ea,viewer);
}
return false;
}

default:
return false;
default:
return false;
}
}

Expand All @@ -163,119 +152,85 @@ void PickHandler::pick(const osgGA::GUIEventAdapter& ea, osgViewer::View* viewer
osg::Node* scene = viewer->getSceneData();
if (!scene) return;

osg::notify(osg::NOTICE)<<std::endl;

osg::Node* node = 0;

if (_usePolytopeIntersector)
{
osgUtil::PolytopeIntersector* picker;
if (_useWindowCoordinates)
{
// use window coordinates
// remap the mouse x,y into viewport coordinates.
osg::Viewport* viewport = viewer->getCamera()->getViewport();
double mx = viewport->x() + (int)((double )viewport->width()*(ea.getXnormalized()*0.5+0.5));
double my = viewport->y() + (int)((double )viewport->height()*(ea.getYnormalized()*0.5+0.5));

// half width, height.
double w = 5.0f;
double h = 5.0f;
picker = new osgUtil::PolytopeIntersector( osgUtil::Intersector::WINDOW, mx-w, my-h, mx+w, my+h );
} else {
double mx = ea.getXnormalized();
double my = ea.getYnormalized();
double w = 0.05;
double h = 0.05;
picker = new osgUtil::PolytopeIntersector( osgUtil::Intersector::PROJECTION, mx-w, my-h, mx+w, my+h );
}
osgUtil::IntersectionVisitor iv(picker);

viewer->getCamera()->accept(iv);

if (picker->containsIntersections())
{
for(std::multiset<osgUtil::PolytopeIntersector::Intersection>::iterator it = picker->getIntersections().begin();
it != picker->getIntersections().end(); it++)
{
const osgUtil::PolytopeIntersector::Intersection &intersection = *it;

/*
osg::notify(osg::NOTICE)<<"Picked "<<intersection.localIntersectionPoint<<std::endl
<<" Distance to ref. plane "<<intersection.distance
<<", max. dist "<<intersection.maxDistance
<<", primitive index "<<intersection.primitiveIndex
<<", numIntersectionPoints "
<<intersection.numIntersectionPoints
<<std::endl;
*/
const osg::NodePath& nodePath = intersection.nodePath;
node = (nodePath.size()>=1)?nodePath[nodePath.size()-1]:0;

//osg::Matrixd l2w = osg::computeLocalToWorld( nodePath );
//osg::Vec3 global = *intersection.matrix.get() * intersection.localIntersectionPoint;
osg::Vec3 global = intersection.localIntersectionPoint * *intersection.matrix.get();

QVector3D globalPoint( global.x(), global.y(), global.z());
emit picked(globalPoint);
}
}
//projection space is [-1 ... 1], thus we can directly use the normalized
//mouse coordinates
double mx = ea.getXnormalized();
double my = ea.getYnormalized();
double w = 0.01;
double h = 0.01;
osg::ref_ptr<osgUtil::PolytopeIntersector> picker;
picker = new osgUtil::PolytopeIntersector( osgUtil::Intersector::PROJECTION, mx-w, my-h, mx+w, my+h );
picker->setIntersectionLimit(osgUtil::Intersector::LIMIT_ONE_PER_DRAWABLE);// a single drawable will appear at most once while calculating intersections.

osgUtil::IntersectionVisitor iv(picker);
viewer->getCamera()->accept(iv);

if (picker->containsIntersections())
{
const osgUtil::PolytopeIntersector::Intersection intersection = picker->getFirstIntersection();
const osg::NodePath& nodePath = intersection.nodePath;
osg::Vec3 global = intersection.localIntersectionPoint * *intersection.matrix.get();
pickNodePath(nodePath, global, viewer);
}
}
else
{
osgUtil::LineSegmentIntersector* picker;
if (!_useWindowCoordinates)
{
// use non dimensional coordinates - in projection/clip space
picker = new osgUtil::LineSegmentIntersector( osgUtil::Intersector::PROJECTION, ea.getXnormalized(),ea.getYnormalized() );
} else {
// use window coordinates
// remap the mouse x,y into viewport coordinates.
osg::Viewport* viewport = viewer->getCamera()->getViewport();
float mx = viewport->x() + (int)((float)viewport->width()*(ea.getXnormalized()*0.5f+0.5f));
float my = viewport->y() + (int)((float)viewport->height()*(ea.getYnormalized()*0.5f+0.5f));
picker = new osgUtil::LineSegmentIntersector( osgUtil::Intersector::WINDOW, mx, my );
}
osgUtil::IntersectionVisitor iv(picker);

viewer->getCamera()->accept(iv);

if (picker->containsIntersections())
{
osgUtil::LineSegmentIntersector::Intersection intersection = picker->getFirstIntersection();

osg::NodePath& nodePath = intersection.nodePath;
node = (nodePath.size()>=1)?nodePath[nodePath.size()-1]:0;

// see if the object has a user object which is derived from pickcallback
PickedCallback *pc = dynamic_cast<PickedCallback*>(node->getUserData());
if( pc )
pc->picked();

for(int i = nodePath.size()-1; i >= 0; i--)
{
osg::Node *node = nodePath[i];
osg::Referenced *user_data = node->getUserData();
if (!user_data)
continue;
PickedUserData *plugin_data = dynamic_cast<PickedUserData*>(user_data);
if(!plugin_data)
continue;

// Transform OSG viewport coordinates to QWidget coordinates (invert y axis)
float wy = (float)viewer->getCamera()->getViewport()->height() - _my;
float wx = _mx;
plugin_data->getPlugin()->click(wx, wy);

osg::Vec3 global = intersection.localIntersectionPoint * *intersection.matrix.get();
emit plugin_data->getPlugin()->picked(global.x(),global.y(),global.z());
break;
}
// setTrackedNode(viewer, node);
}
osg::ref_ptr<osgUtil::LineSegmentIntersector> picker;

// use non dimensional coordinates - in projection/clip space
picker = new osgUtil::LineSegmentIntersector( osgUtil::Intersector::PROJECTION, ea.getXnormalized(),ea.getYnormalized() );
// Using this setting, a single drawable will appear at most once while calculating intersections.
picker->setIntersectionLimit(osgUtil::Intersector::LIMIT_ONE_PER_DRAWABLE);
osgUtil::IntersectionVisitor iv(picker);
viewer->getCamera()->accept(iv);

if (picker->containsIntersections())
{
osgUtil::LineSegmentIntersector::Intersection intersection = picker->getFirstIntersection();
const osg::NodePath& nodePath = intersection.nodePath;
const osg::Vec3 global = intersection.localIntersectionPoint * *intersection.matrix.get();
pickNodePath(nodePath, global, viewer);
}
}
}

void PickHandler::pickNodePath(const osg::NodePath& nodePath, osg::Vec3 global,
osgViewer::View* viewer) const
{
if(nodePath.empty())
return;

osg::Node* node = nodePath[nodePath.size()-1];
// see if the object has a user object which is derived from pickcallback
PickedCallback *pc = dynamic_cast<PickedCallback*>(node->getUserData());
if( pc )
pc->picked();

for(int i = nodePath.size()-1; i >= 0; i--)
{
osg::Node *node = nodePath[i];
osg::Referenced *user_data = node->getUserData();
if (!user_data)
continue;
PickedUserData *plugin_data = dynamic_cast<PickedUserData*>(user_data);
if(!plugin_data)
continue;

// Transform OSG viewport coordinates to QWidget coordinates (invert y axis)
float wy = (float)viewer->getCamera()->getViewport()->height() - _my;
float wx = _mx;
plugin_data->getPlugin()->click(wx, wy);
emit plugin_data->getPlugin()->picked(global.x(),global.y(),global.z());
break;
}

const QVector3D globalPoint( global.x(), global.y(), global.z());
emit picked(globalPoint);
emit pickedNodePath(nodePath);
}

void PickHandler::setTrackedNode(osgViewer::View* viewer, osg::ref_ptr< osg::Node > node)
{
osgGA::KeySwitchMatrixManipulator *keyswitchManipulator =
Expand Down
11 changes: 9 additions & 2 deletions src/PickHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,24 @@ class PickHandler : public QObject, public osgGA::GUIEventHandler
void pick(const osgGA::GUIEventAdapter& ea, osgViewer::View* viewer);

signals:
void picked(const QVector3D& coord);
void picked(const QVector3D& coord) const;
/**Is emitted whenenver the user picks a node.
* @p path The path from the root node to the picked node*/
void pickedNodePath(const osg::NodePath& path) const;

protected:
void setTrackedNode(osgViewer::View* viewer, osg::ref_ptr< osg::Node > node);

/** @param nodePath NodePath to the picked node
* @param global global coordinates of the clicked point*/
void pickNodePath(const osg::NodePath& nodePath, osg::Vec3 global,
osgViewer::View* viewer) const;

void wireFrameModeOn(osg::Node *srcNode);
void wireFrameModeOff(osg::Node *srcNode);

float _mx,_my;
bool _usePolytopeIntersector;
bool _useWindowCoordinates;

typedef std::map<int, functionStatusType > keyFunctionMap;
keyFunctionMap keyFuncMap;
Expand Down
Loading