查看: 3820|回复: 11

osg三维场景中如何实现多边形选择与矩形选择

[复制链接]

该用户从未签到

发表于 2011-11-29 15:32:36 | 显示全部楼层 |阅读模式
   osg三维场景中如何实现多边形选择与矩形选择,看一些人说用osgutil::IntersectionVisitor,跟HUD,我仿照osg中带的例子实现了下,但是始终得不到我想要的那结果,最近一直在搞这个,一直都没有进展,哪位高手实现过类似的功能,指点下我啊,小女子感激不尽啊!

该用户从未签到

发表于 2011-11-29 15:48:15 | 显示全部楼层
你把你的程序传上来我帮你看一下吧

该用户从未签到

 楼主| 发表于 2011-11-30 15:11:21 | 显示全部楼层
本帖最后由 kyl5451 于 2011-11-30 15:20 编辑

bool PickHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
    {
                osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
                if (!viewer) return false;

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

该用户从未签到

 楼主| 发表于 2011-11-30 15:12:49 | 显示全部楼层
本帖最后由 kyl5451 于 2011-11-30 15:20 编辑

void PickHandler:: pick(float mx,float my,float mxx,float myy,osgViewer::Viewer* viewer)
        {  
                osg::ref_ptr<osg::Node> scene = viewer->getSceneData();
                if (!scene) return;

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

                osg::ref_ptr<osg::Node>node=new osg::Node();
                osg::ref_ptr<osg::Group>parent=new osg::Group();
                osg::ref_ptr< osgUtil::PolytopeIntersector> picker;
                picker = new osgUtil::PolytopeIntersector( osgUtil::Intersector::WINDOW, mx, my, mxx, myy );
                //创建一个交集访问器
                osgUtil::IntersectionVisitor iv(picker);

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

                if (picker->containsIntersections())
                {
                        osgUtil::PolytopeIntersector::Intersection intersection = picker->getFirstIntersection();
                        osg::NodePath& nodePath = intersection.nodePath;
                        node = (nodePath.size()>=1)?nodePath[nodePath.size()-1]:0;
                        parent = (nodePath.size()>=2)?dynamic_cast<osg::Group*>(nodePath[nodePath.size()-2]):0;

                        if (node) std::cout<<"  Hits "<<node->className()<<" nodePath size "<<nodePath.size()<<std::endl;   
                        toggleScribe(parent, node);
                }
        }

该用户从未签到

 楼主| 发表于 2011-11-30 15:13:26 | 显示全部楼层
本帖最后由 kyl5451 于 2011-11-30 15:21 编辑

class CreateHUD
{
public:
        CreateHUD()
        {

        }
        ~CreateHUD()
        {

        }
        //创建HUD
        osg::ref_ptr<osg::Node> creatHUD(osg::ref_ptr<osgText::Text>updateText)
        {
                //创建一个相机
                osg::ref_ptr<osg::Camera>hudCamera=new osg::Camera;
                //设置绝对真引用
                hudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
                //设置正投影矩阵
                hudCamera->setProjectionMatrixAsOrtho2D(0,1280,0,1024);
                //设置视图矩阵
                hudCamera->setViewMatrix(osg::Matrix::identity());
                //设置渲染顺序为post
                hudCamera->setRenderOrder(osg::Camera::POST_RENDER);
                //清除深度缓存
                hudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);
                //设置字体
                std::string timesFont("fonts//cpur.ttf");
                //设置位置
                osg::Vec3 position(700,900,0.0);

                osg::ref_ptr<osg::Geode>geode=new osg::Geode();
                osg::ref_ptr<osg::StateSet>stateset=geode->getOrCreateStateSet();
                //关闭光照
                stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
                //关闭深度测试
                stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
                geode->addDrawable(updateText.get());
                hudCamera->addChild(geode.get());

                updateText->setCharacterSize(20.0f);
                updateText->setFont(timesFont);
                updateText->setColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
                updateText->setText("");
                updateText->setPosition(position);
                //设置数据变量        DYNAMIC
                updateText->setDataVariance(osg::Object::DYNAMIC);

                return hudCamera.get();



        }
};

该用户从未签到

 楼主| 发表于 2011-11-30 15:15:46 | 显示全部楼层
本帖最后由 kyl5451 于 2011-11-30 15:22 编辑

主要就是想通过鼠标点击移动,获取两个坐标,然后用pick实现以这两个坐标为顶点的框选,并高亮显示, toggleScribe(parent, node)这个函数是高亮显示的;
但是我现在这样写,只能实现点选,不能框选,请高手指点下啊
HUD主要是想实现画线框,但是我main函数中用了之后也不能实现画线框;

该用户从未签到

发表于 2011-11-30 18:44:12 | 显示全部楼层
我看过你的代码了 看来你需要将array的书好好看一下,再把osg的示例程序认真看一下.1.首先实现框选,push的时候获取首点坐标(mx,my),move里面你没有任何代码,release后获取第二个点坐标(mxx,myy),按照PolytopeIntersector的参数含义应该是x的最小值,y的最小值,x的最大值,y的最大值, 2.picker->getFirstIntersection也不对,框选应该将所有的交集都要高亮的,所以应该用picker->getIntersections 然后用迭代器遍历,将所有的对象高亮 3.如果你想用HUD画矩形的边框,那你就得在move里不停的删除矩形,绘制矩形才行,绘制矩形应该使用Geometry,而不是Text

该用户从未签到

 楼主| 发表于 2011-12-5 09:48:49 | 显示全部楼层
garyliyong 发表于 2011-11-30 18:44
我看过你的代码了 看来你需要将array的书好好看一下,再把osg的示例程序认真看一下.1.首先实现框选,push的时 ...

嗯,这两天看了下书又,但是关于怎么实现选择框那里还是不大会实现,就是handle函数里面,push,move release那里怎么操作,才能实现框选中一个区域内的所有物体呢?请指教下

该用户从未签到

发表于 2011-12-5 22:17:47 | 显示全部楼层
kyl5451 发表于 2011-12-5 09:48
嗯,这两天看了下书又,但是关于怎么实现选择框那里还是不大会实现,就是handle函数里面,push,move rel ...

这样吧 我明天写个简单的框选示例程序传上来,实现框选,至于矩形框你自己绘制吧

该用户从未签到

发表于 2011-12-6 21:43:37 | 显示全部楼层
garyliyong 发表于 2011-12-5 22:17
这样吧 我明天写个简单的框选示例程序传上来,实现框选,至于矩形框你自己绘制吧

我将例子改写了一下,实现了框选,高亮部分不完善,你自己改写吧
  1. /* OpenSceneGraph example, osgkeyboardmouse.
  2. *
  3. *  Permission is hereby granted, free of charge, to any person obtaining a copy
  4. *  of this software and associated documentation files (the "Software"), to deal
  5. *  in the Software without restriction, including without limitation the rights
  6. *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. *  copies of the Software, and to permit persons to whom the Software is
  8. *  furnished to do so, subject to the following conditions:
  9. *
  10. *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  11. *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  12. *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  13. *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  14. *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  15. *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  16. *  THE SOFTWARE.
  17. */

  18. // Simple example of use of osgViewer::GraphicsWindow + Viewer
  19. // example that provides the user with control over view position with basic picking.

  20. #include <osg/Timer>
  21. #include <osg/io_utils>
  22. #include <osg/observer_ptr>

  23. #include <osgUtil/IntersectionVisitor>
  24. #include <osgUtil/PolytopeIntersector>
  25. #include <osgUtil/LineSegmentIntersector>

  26. #include <osgDB/ReadFile>
  27. #include <osgDB/WriteFile>

  28. #include <osgGA/TrackballManipulator>
  29. #include <osgGA/StateSetManipulator>

  30. #include <osgViewer/Viewer>

  31. #include <osgFX/Scribe>

  32. #include <iostream>
  33. #include <osg/MatrixTransform>

  34. // class to handle events with a pick
  35. class PickHandler : public osgGA::GUIEventHandler
  36. {
  37. public:

  38.     PickHandler():
  39.       _mx(0.0),_my(0.0)
  40.      {}

  41.       ~PickHandler() {}

  42.       bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
  43.       {
  44.           osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
  45.           if (!viewer) return false;
  46.           ea.setHandled(true);
  47.           switch(ea.getEventType())
  48.           {
  49.           case(osgGA::GUIEventAdapter::PUSH):
  50.               {
  51.                   _mx = ea.getX();
  52.                   _my = ea.getY();
  53.               }
  54.               break;
  55.           case(osgGA::GUIEventAdapter::DRAG):
  56.               {
  57.                   _nx = ea.getX();
  58.                   _ny = ea.getY();
  59.               }
  60.               break;
  61.           case(osgGA::GUIEventAdapter::RELEASE):
  62.               {
  63.                       pick(ea,viewer);
  64.               }   
  65.               break;
  66.           default:
  67.              break;
  68.           }
  69.            return true;
  70.       }

  71.       void pick(const osgGA::GUIEventAdapter& ea, osgViewer::Viewer* viewer)
  72.       {
  73.           osg::Node* scene = viewer->getSceneData();
  74.           if (!scene) return;

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

  76.           osg::Node* node = 0;
  77.           osg::Group* parent = 0;

  78.               osgUtil::PolytopeIntersector* picker;
  79.               
  80.                   // use window coordinates
  81.                   // remap the mouse x,y into viewport coordinates.
  82.                  
  83.                   // half width, height.
  84.               double mx = ea.getX();
  85.               double my = ea.getY();
  86.               double minX,minY,maxX,maxY;
  87.               if (mx > _mx)
  88.               {
  89.                   minX = _mx;
  90.                   maxX = mx;
  91.               }
  92.               else
  93.               {
  94.                   minX = mx;
  95.                   maxX = _mx;
  96.               }

  97.               if (my > _my)
  98.               {
  99.                   minY = _my;
  100.                   maxY = my;
  101.               }
  102.               else
  103.               {
  104.                   minY = my;
  105.                   maxY = _my;
  106.               }
  107.               picker = new osgUtil::PolytopeIntersector( osgUtil::Intersector::WINDOW,
  108.                  minX,minY,maxX,maxY);
  109.               
  110.               osgUtil::IntersectionVisitor iv(picker);

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

  112.               if (picker->containsIntersections())
  113.               {
  114.                   osgUtil::PolytopeIntersector::Intersections intersections;
  115.                   osgUtil::PolytopeIntersector::Intersections::iterator iter;

  116.                   intersections = picker->getIntersections();
  117.                   for (iter = intersections.begin();iter!= intersections.end();iter++)
  118.                   {
  119.                       osg::NodePath nodePath = (*iter).nodePath;
  120.                       node = (nodePath.size()>=1)?nodePath[nodePath.size()-1]:0;
  121.                       parent = (nodePath.size()>=2)?dynamic_cast<osg::Group*>(nodePath[nodePath.size()-2]):0;

  122.                       if (node)
  123.                       {
  124.                             toggleScribe(parent, node);
  125.                       }
  126.                      
  127.                   }
  128.               }
  129.       }

  130.       void toggleScribe(osg::Group* parent, osg::Node* node)
  131.       {
  132.           if (!parent || !node) return;

  133.          

  134.           osgFX::Scribe* parentAsScribe = dynamic_cast<osgFX::Scribe*>(parent);
  135.           if (!parentAsScribe)
  136.           {
  137.               // node not already picked, so highlight it with an osgFX::Scribe
  138.               osgFX::Scribe* scribe = new osgFX::Scribe();
  139.               scribe->addChild(node);
  140.               parent->replaceChild(node,scribe);
  141.           }
  142.           else
  143.           {
  144.               // node already picked so we want to remove scribe to unpick it.
  145.               osg::Node::ParentList parentList = parentAsScribe->getParents();
  146.               for(osg::Node::ParentList::iterator itr=parentList.begin();
  147.                   itr!=parentList.end();
  148.                   ++itr)
  149.               {
  150.                   (*itr)->replaceChild(parentAsScribe,node);
  151.               }
  152.           }
  153.       }

  154.    
  155. protected:

  156.     float _mx,_my;
  157.     float _nx,_ny;
  158. };

  159. int main( int argc, char **argv )
  160. {
  161.     osg::ref_ptr<osg::Group> loadedModel;

  162.     loadedModel = new osg::Group;
  163.     loadedModel->addChild(osgDB::readNodeFile("cow.osg"));

  164.     osg::ref_ptr<osg::MatrixTransform> mat = new osg::MatrixTransform();
  165.     mat->setMatrix(osg::Matrix::translate(10,0,0));
  166.     mat->addChild(osgDB::readNodeFile("glider.osg"));
  167.     loadedModel->addChild(mat);
  168.     // create the window to draw to.
  169.     osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
  170.     traits->x = 200;
  171.     traits->y = 200;
  172.     traits->width = 800;
  173.     traits->height = 600;
  174.     traits->windowDecoration = true;
  175.     traits->doubleBuffer = true;
  176.     traits->sharedContext = 0;

  177.     osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
  178.     osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
  179.     if (!gw)
  180.     {
  181.         osg::notify(osg::NOTICE)<<"Error: unable to create graphics window."<<std::endl;
  182.         return 1;
  183.     }

  184.     // create the view of the scene.
  185.     osgViewer::Viewer viewer;
  186.     viewer.getCamera()->setGraphicsContext(gc.get());
  187.     viewer.getCamera()->setViewport(0,0,800,600);
  188.     viewer.setSceneData(loadedModel.get());

  189.     // create a tracball manipulator to move the camera around in response to keyboard/mouse events
  190.     viewer.setCameraManipulator( new osgGA::TrackballManipulator );

  191.     osg::ref_ptr<osgGA::StateSetManipulator> statesetManipulator = new osgGA::StateSetManipulator(viewer.getCamera()->getStateSet());
  192.     viewer.addEventHandler(statesetManipulator.get());

  193.     // add the pick handler
  194.     viewer.addEventHandler(new PickHandler());

  195.     viewer.realize();

  196.     // main loop (note, window toolkits which take control over the main loop will require a window redraw callback containing the code below.)
  197.     while(!viewer.done())
  198.     {
  199.         viewer.frame();
  200.     }

  201.     return 0;
  202. }

复制代码

该用户从未签到

 楼主| 发表于 2011-12-7 20:57:06 | 显示全部楼层
garyliyong 发表于 2011-12-6 21:43
我将例子改写了一下,实现了框选,高亮部分不完善,你自己改写吧

谢谢您了啊

该用户从未签到

发表于 2011-12-7 21:21:44 | 显示全部楼层
kyl5451 发表于 2011-12-7 20:57
谢谢您了啊

拖拽形成的矩形框,你可以采用HUD做,在DRAG中不断地绘制和删除就行了,在RELEASE的时候把矩形框也要删掉
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表