Added convinence methods to osgProducer::Viewer:

/** compute, from normalized mouse coords, for sepecified Camera, the pixel coords relative to that Camera's RenderSurface.*/
        bool computePixelCoords(float x,float y,unsigned int cameraNum,float& pixel_x,float& pixel_y);

        /** compute, from normalized mouse coords, for sepecified Camera, the near and far points in worlds coords.*/
        bool computeNearFar(float x,float y,unsigned int cameraNum,osg::Vec3& near, osg::Vec3& far);

        /** compute, from normalized mouse coords, for sepecified Camera, intersections with the scene.*/
        bool computeIntersections(float x,float y,unsigned int cameraNum,osgUtil::IntersectVisitor::HitList& hits);

        /** compute, from normalized mouse coords, for all Cameras, intersections with the scene.*/
        bool computeIntersections(float x,float y,osgUtil::IntersectVisitor::HitList& hits);
This commit is contained in:
Robert Osfield 2003-04-16 14:17:49 +00:00
parent 48cb15015f
commit 904aceec22
6 changed files with 160 additions and 134 deletions

View File

@ -28,41 +28,6 @@
#include <osgText/Text> #include <osgText/Text>
#include <osgUtil/PickVisitor>
static Producer::CameraConfig *BuildConfig(void)
{
Producer::RenderSurface *rs1 = new Producer::RenderSurface;
rs1->setScreenNum(0);
//rs1->useBorder(false);
rs1->setWindowRect(0,0,640,480);
Producer::Camera *camera1 = new Producer::Camera;
camera1->setRenderSurface(rs1);
camera1->setOffset( 1.0, 0.0 );
Producer::RenderSurface *rs2 = new Producer::RenderSurface;
rs2->setScreenNum(0);
//rs2->useBorder(false);
rs2->setWindowRect(640,0,640,480);
Producer::Camera *camera2 = new Producer::Camera;
camera2->setRenderSurface(rs2);
camera2->setOffset( -1.0, 0.0 );
Producer::InputArea *ia = new Producer::InputArea;
ia->addInputRectangle( rs1, Producer::InputRectangle(0.0,0.5,0.0,1.0));
ia->addInputRectangle( rs2, Producer::InputRectangle(0.5,1.0,0.0,1.0));
// ia->addInputRectangle( rs1, Producer::InputRectangle(-1.0,0.0,-1.0,1.0));
// ia->addInputRectangle( rs2, Producer::InputRectangle(0.0,1.0,-1.0,1.0));
Producer::CameraConfig *cfg = new Producer::CameraConfig;
cfg->addCamera("Camera 1",camera1);
cfg->addCamera("Camera 2", camera2);
cfg->setInputArea(ia);
return cfg;
}
// class to handle events with a pick // class to handle events with a pick
class PickHandler : public osgGA::GUIEventHandler { class PickHandler : public osgGA::GUIEventHandler {
@ -106,104 +71,33 @@ bool PickHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapte
void PickHandler::pick(const osgGA::GUIEventAdapter& ea) void PickHandler::pick(const osgGA::GUIEventAdapter& ea)
{ {
// OK here is the interesting bit - How To Pick a Geode osgUtil::IntersectVisitor::HitList hlist;
// including geodes in a HUD under a Projection Matrix
osg::Node *scene=_viewer->getSceneData();//main node of the scene. std::string gdlist="";
if (scene) if (_viewer->computeIntersections(ea.getX(),ea.getY(),hlist))
{ {
float x=ea.getX(); for(osgUtil::IntersectVisitor::HitList::iterator hitr=hlist.begin();
float y=ea.getY(); hitr!=hlist.end();
++hitr)
Producer::KeyboardMouse* km = _viewer->getKeyboardMouse();
std::string gdlist="";
for(unsigned int i=0;i<_viewer->getNumberOfCameras();++i)
{ {
Producer::Camera* cmm=_viewer->getCamera(i); //osg::Vec3 ip = hitr->getLocalIntersectPoint();
Producer::RenderSurface* rs = cmm->getRenderSurface(); //osg::Vec3 in = hitr->getLocalIntersectNormal();
osg::Geode* geode = hitr->_geode.get();
//std::cout << "checking camara "<<i<<std::endl; // the geodes are identified by name.
if (geode)
float pixel_x,pixel_y;
if (km->computePixelCoords(x,y,rs,pixel_x,pixel_y))
{ {
//std::cout << " compute pixel coords "<<pixel_x<<" "<<pixel_y<<std::endl; if (!geode->getName().empty())
int pr_wx, pr_wy;
unsigned int pr_width, pr_height;
cmm->getProjectionRect( pr_wx, pr_wy, pr_width, pr_height );
int rs_wx, rs_wy;
unsigned int rs_width, rs_height;
rs->getWindowRect( rs_wx, rs_wy, rs_width, rs_height );
pr_wx += rs_wx;
pr_wy += rs_wy;
//std::cout << " wx = "<<pr_wx<<" wy = "<<pr_wy<<" width="<<pr_width<<" height="<<pr_height<<std::endl;
if (pixel_x<(float)pr_wx) break;
if (pixel_x>(float)(pr_wx+pr_width)) break;
if (pixel_y<(float)pr_wy) break;
if (pixel_y>(float)(pr_wy+pr_height)) break;
float rx = 2.0f*(pixel_x - (float)pr_wx)/(float)pr_width-1.0f;
float ry = 2.0f*(pixel_y - (float)pr_wy)/(float)pr_height-1.0f;
//std::cout << " rx "<<rx<<" "<<ry<<std::endl;
osgProducer::OsgSceneHandler* sh = dynamic_cast<osgProducer::OsgSceneHandler*>(cmm->getSceneHandler());
osg::Matrix vum;
if (sh!=0 && sh->getModelViewMatrix()!=0 && sh->getProjectionMatrix()!=0)
{ {
vum.set((*(sh->getModelViewMatrix())) * gdlist=gdlist+" "+geode->getName();
(*(sh->getProjectionMatrix())));
} }
else else
{ {
vum.set(osg::Matrix(cmm->getViewMatrix()) * gdlist=gdlist+" geode";
osg::Matrix(cmm->getProjectionMatrix())/* *
osg::Matrix::translate(1.0f,1.0f,1.0f) *
osg::Matrix::scale(0.5f,0.5f,0.5f)*/);
} }
}
osgUtil::PickVisitor iv;
osgUtil::IntersectVisitor::HitList& hlist=iv.getHits(scene, vum, rx,ry);
if (iv.hits())
{
for(osgUtil::IntersectVisitor::HitList::iterator hitr=hlist.begin();
hitr!=hlist.end();
++hitr)
{
//osg::Vec3 ip = hitr->getLocalIntersectPoint();
//osg::Vec3 in = hitr->getLocalIntersectNormal();
osg::Geode* geode = hitr->_geode.get();
// the geodes are identified by name.
if (geode)
{
if (!geode->getName().empty())
{
gdlist=gdlist+" "+geode->getName();
}
else
{
gdlist=gdlist+" geode";
}
}
}
}
}
} }
setLabel(gdlist);
} }
setLabel(gdlist);
} }
osg::Node* createHUD(osgText::Text* updateText) osg::Node* createHUD(osgText::Text* updateText)
@ -311,8 +205,7 @@ int main( int argc, char **argv )
// construct the viewer. // construct the viewer.
//osgProducer::Viewer viewer(arguments); osgProducer::Viewer viewer(arguments);
osgProducer::Viewer viewer(BuildConfig());
// set up the value with sensible default event handlers. // set up the value with sensible default event handlers.
viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS); viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

View File

@ -20,6 +20,8 @@
#include <osg/ApplicationUsage> #include <osg/ApplicationUsage>
#include <osg/AnimationPath> #include <osg/AnimationPath>
#include <osgUtil/IntersectVisitor>
#include <osgGA/GUIActionAdapter> #include <osgGA/GUIActionAdapter>
#include <osgGA/GUIEventHandler> #include <osgGA/GUIEventHandler>
#include <osgGA/KeySwitchCameraManipulator> #include <osgGA/KeySwitchCameraManipulator>
@ -92,14 +94,27 @@ class OSGPRODUCER_EXPORT Viewer : public OsgCameraGroup, public osgGA::GUIAction
virtual void requestContinuousUpdate(bool) {} virtual void requestContinuousUpdate(bool) {}
virtual void requestWarpPointer(float x,float y); virtual void requestWarpPointer(float x,float y);
Producer::KeyboardMouse* getKeyboardMouse() { return _kbmcb==0?0:_kbmcb->getKeyboardMouse(); }
const Producer::KeyboardMouse* getKeyboardMouse() const { return _kbmcb==0?0:_kbmcb->getKeyboardMouse(); } /** compute, from normalized mouse coords, for sepecified Camera, the pixel coords relative to that Camera's RenderSurface.*/
bool computePixelCoords(float x,float y,unsigned int cameraNum,float& pixel_x,float& pixel_y);
/** compute, from normalized mouse coords, for sepecified Camera, the near and far points in worlds coords.*/
bool computeNearFar(float x,float y,unsigned int cameraNum,osg::Vec3& near, osg::Vec3& far);
KeyboardMouseCallback* getKeyboardMouseCallback() { return _kbmcb; } /** compute, from normalized mouse coords, for sepecified Camera, intersections with the scene.*/
bool computeIntersections(float x,float y,unsigned int cameraNum,osgUtil::IntersectVisitor::HitList& hits);
/** compute, from normalized mouse coords, for all Cameras, intersections with the scene.*/
bool computeIntersections(float x,float y,osgUtil::IntersectVisitor::HitList& hits);
Producer::KeyboardMouse* getKeyboardMouse() { return _kbmcb==0?0:_kbmcb->getKeyboardMouse(); }
const Producer::KeyboardMouse* getKeyboardMouse() const { return _kbmcb==0?0:_kbmcb->getKeyboardMouse(); }
KeyboardMouseCallback* getKeyboardMouseCallback() { return _kbmcb; }
const KeyboardMouseCallback* getKeyboardMouseCallback() const { return _kbmcb; } const KeyboardMouseCallback* getKeyboardMouseCallback() const { return _kbmcb; }
typedef std::list< osg::ref_ptr<osgGA::GUIEventHandler> > EventHandlerList; typedef std::list< osg::ref_ptr<osgGA::GUIEventHandler> > EventHandlerList;
EventHandlerList& getEventHandlerList() { return _eventHandlerList; } EventHandlerList& getEventHandlerList() { return _eventHandlerList; }

View File

@ -10,6 +10,9 @@ osgviewer cow.osg
echo osgkeyboard echo osgkeyboard
osgkeyboard osgkeyboard
echo osgpick fountain.osg
osgpick fountain.osg
echo osgwindows glider.osg echo osgwindows glider.osg
osgwindows glider.osg osgwindows glider.osg

View File

@ -2,6 +2,7 @@
#include <osg/ApplicationUsage> #include <osg/ApplicationUsage>
#include <osgUtil/UpdateVisitor> #include <osgUtil/UpdateVisitor>
#include <osgUtil/PickVisitor>
#include <osgDB/Registry> #include <osgDB/Registry>
@ -299,6 +300,116 @@ void Viewer::frame()
OsgCameraGroup::frame(); OsgCameraGroup::frame();
} }
bool Viewer::computePixelCoords(float x,float y,unsigned int cameraNum,float& pixel_x,float& pixel_y)
{
Producer::KeyboardMouse* km = getKeyboardMouse();
if (!km) return false;
if (cameraNum>=getNumberOfCameras()) return false;
Producer::Camera* camera=getCamera(cameraNum);
Producer::RenderSurface* rs = camera->getRenderSurface();
//std::cout << "checking camara "<<i<<std::endl;
if (km->computePixelCoords(x,y,rs,pixel_x,pixel_y))
{
//std::cout << " compute pixel coords "<<pixel_x<<" "<<pixel_y<<std::endl;
int pr_wx, pr_wy;
unsigned int pr_width, pr_height;
camera->getProjectionRect( pr_wx, pr_wy, pr_width, pr_height );
int rs_wx, rs_wy;
unsigned int rs_width, rs_height;
rs->getWindowRect( rs_wx, rs_wy, rs_width, rs_height );
pixel_x -= (float)rs_wx;
pixel_y -= (float)rs_wy;
//std::cout << " wx = "<<pr_wx<<" wy = "<<pr_wy<<" width="<<pr_width<<" height="<<pr_height<<std::endl;
if (pixel_x<(float)pr_wx) return false;
if (pixel_x>(float)(pr_wx+pr_width)) return false;
if (pixel_y<(float)pr_wy) return false;
if (pixel_y>(float)(pr_wy+pr_height)) return false;
return true;
}
return false;
}
bool Viewer::computeNearFar(float x,float y,unsigned int cameraNum,osg::Vec3& near, osg::Vec3& far)
{
if (cameraNum>=getSceneHandlerList().size()) return false;
OsgSceneHandler* scenehandler = getSceneHandlerList()[cameraNum].get();
float pixel_x,pixel_y;
if (computePixelCoords(x,y,cameraNum,pixel_x,pixel_y))
{
return scenehandler->projectWindowXYIntoObject(pixel_x,pixel_y,near,far);
}
return false;
}
bool Viewer::computeIntersections(float x,float y,unsigned int cameraNum,osgUtil::IntersectVisitor::HitList& hits)
{
float pixel_x,pixel_y;
if (computePixelCoords(x,y,cameraNum,pixel_x,pixel_y))
{
Producer::Camera* camera=getCamera(cameraNum);
int pr_wx, pr_wy;
unsigned int pr_width, pr_height;
camera->getProjectionRect( pr_wx, pr_wy, pr_width, pr_height );
// convert into clip coords.
float rx = 2.0f*(pixel_x - (float)pr_wx)/(float)pr_width-1.0f;
float ry = 2.0f*(pixel_y - (float)pr_wy)/(float)pr_height-1.0f;
//std::cout << " rx "<<rx<<" "<<ry<<std::endl;
osgProducer::OsgSceneHandler* sh = dynamic_cast<osgProducer::OsgSceneHandler*>(camera->getSceneHandler());
osg::Matrix vum;
if (sh!=0 && sh->getModelViewMatrix()!=0 && sh->getProjectionMatrix()!=0)
{
vum.set((*(sh->getModelViewMatrix())) *
(*(sh->getProjectionMatrix())));
}
else
{
vum.set(osg::Matrix(camera->getViewMatrix()) *
osg::Matrix(camera->getProjectionMatrix()));
}
osgUtil::PickVisitor iv;
osgUtil::IntersectVisitor::HitList localHits;
localHits = iv.getHits(getSceneData(), vum, rx,ry);
if (localHits.empty()) return false;
hits.insert(hits.begin(),localHits.begin(),localHits.end());
return true;
}
return false;
}
bool Viewer::computeIntersections(float x,float y,osgUtil::IntersectVisitor::HitList& hits)
{
bool hitFound = false;
osgUtil::IntersectVisitor::HitList hlist;
for(unsigned int i=0;i<getNumberOfCameras();++i)
{
if (computeIntersections(x,y,i,hits)) hitFound = true;
}
return hitFound;
}
void Viewer::selectCameraManipulator(unsigned int no) void Viewer::selectCameraManipulator(unsigned int no)
{ {

View File

@ -33,9 +33,10 @@ public:
image->readPixels(x,y,width,height, image->readPixels(x,y,width,height,
GL_RGB,GL_UNSIGNED_BYTE); GL_RGB,GL_UNSIGNED_BYTE);
osgDB::writeImageFile(*image,_filename); if (osgDB::writeImageFile(*image,_filename))
{
osg::notify(osg::NOTICE) << "Saved screen image to `"<<_filename<<"`"<< std::endl; osg::notify(osg::NOTICE) << "Saved screen image to `"<<_filename<<"`"<< std::endl;
}
_snapImageOnNextFrame = false; _snapImageOnNextFrame = false;
} }
@ -802,8 +803,10 @@ bool ViewerEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActio
osg::Node* node = _cg->getSceneData(); osg::Node* node = _cg->getSceneData();
if (node) if (node)
{ {
std::cout<<"writing file "<<_writeNodeFileName<<std::endl; if (osgDB::writeNodeFile(*node,_writeNodeFileName.c_str()))
osgDB::writeNodeFile(*node,_writeNodeFileName.c_str()); {
std::cout<<"writen nodes to file "<<_writeNodeFileName<<std::endl;
}
} }
return true; return true;

View File

@ -107,7 +107,8 @@ osgUtil::IntersectVisitor::HitList& PickVisitor::getHits(osg::Node *scene,
void PickVisitor::apply(osg::Projection& pr) void PickVisitor::apply(osg::Projection& pr)
{ // stack the intersect rays, transform to new projection, traverse { // stack the intersect rays, transform to new projection, traverse
// Assumes that the Projection is an absolute projection // Assumes that the Projection is an absolute projection
osg::Matrix mt=osg::Matrix::inverse(pr.getMatrix()); osg::Matrix mt;
mt.invert(pr.getMatrix());
osg::Vec3 npt=osg::Vec3(xp,yp,1.0f) * mt, farpt=osg::Vec3(xp,yp,-1.0f) * mt; osg::Vec3 npt=osg::Vec3(xp,yp,1.0f) * mt, farpt=osg::Vec3(xp,yp,-1.0f) * mt;
// traversing the nodes children, using the projection direction // traversing the nodes children, using the projection direction