查看: 2895|回复: 23

框选效率问题

[复制链接]

该用户从未签到

发表于 2011-11-9 18:55:52 | 显示全部楼层 |阅读模式
我使用PolytopeIntersector实现框选并高亮所选节点,在数据量大的时候,会有很明显的延迟,帧数也下降,不知道哪位大侠有没有好的实现方法? 我今天还有PlaneIntersector这个类不知道效率如何?

该用户从未签到

发表于 2011-11-10 12:56:20 | 显示全部楼层
这个是必然的,如果想实现高效率的求交,您需要考虑一些空间索引的策略,比如RTree等等,并且自己实现相应的算法

该用户从未签到

发表于 2011-11-22 17:19:53 | 显示全部楼层
今天也遇到了框选效率问题,于是对PolytopeIntersecto源码进行分析,发现PolytopeIntersecto对一个drawable产生了成千上万个交点(影响求交效率),并再结果里也加入了成千上万个Intersection(影响你对结果的遍历效率),于是对其进行了简单的优化操作,效率提升很多,主要针对两个方面进行了优化:
1、如果一个drawable已经和polytope相交,则不再继续求交点
2、如果一个drawable与polytope有多个交点,只往结果里添加一个Intersection(实际上优化了1,2就没必要)

该用户从未签到

 楼主| 发表于 2011-11-22 18:24:59 | 显示全部楼层
本帖最后由 garyliyong 于 2011-11-22 19:28 编辑

代码我也看过了,确实是这样,那你是修改源代码还是写个类继承PolytopeIntersector呢?该如何添加代码呢?谢谢

该用户从未签到

发表于 2011-11-23 09:09:22 | 显示全部楼层
简单的把PolytopeIntersector从osg里拷贝出来,然后换个类名进行修改即可

该用户从未签到

 楼主| 发表于 2011-11-24 13:16:25 | 显示全部楼层
fenma3422 发表于 2011-11-23 09:09
简单的把PolytopeIntersector从osg里拷贝出来,然后换个类名进行修改即可

昨天我对算法改进了一下,确实是效率提高不少,我特意试了一个很大的文件,一点也没问题,谢谢你

该用户从未签到

发表于 2013-3-18 10:14:47 | 显示全部楼层
garyliyong 发表于 2011-11-24 13:16
昨天我对算法改进了一下,确实是效率提高不少,我特意试了一个很大的文件,一点也没问题,谢谢你

您好,我是个osg新手。最近也在做框选方面的效果。对于上面所提到的算法简化,原理上差不多懂了,但还请您指点一下源码中的修改,是修改“void PolytopeIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg:rawable* drawable)”这部分吗?

该用户从未签到

发表于 2013-3-18 10:36:04 | 显示全部楼层
mxl12315 发表于 2013-3-18 10:14
您好,我是个osg新手。最近也在做框选方面的效果。对于上面所提到的算法简化,原理上差不多懂了,但还请您 ...

记录一下测试过的drawable,然后比较,就在这个函数中

该用户从未签到

 楼主| 发表于 2013-3-18 19:38:24 | 显示全部楼层
本帖最后由 garyliyong 于 2013-3-19 10:09 编辑
mxl12315 发表于 2013-3-18 10:14
您好,我是个osg新手。最近也在做框选方面的效果。对于上面所提到的算法简化,原理上差不多懂了,但还请您 ...


其实就是判断一下当前的drawable已经有交点了,就不需要再计算了。在这个函数里面有个求交器,主要是遍历点,线,三角形,计算交点  最后保存交点信息的地方也可以修改的,如果只是判断是否相交就不需要保存交点信息的

该用户从未签到

发表于 2013-3-19 13:39:44 | 显示全部楼层
感谢楼上二位高手的耐心指点,我这就去试试~

该用户从未签到

发表于 2013-3-20 11:00:36 | 显示全部楼层
本帖最后由 mxl12315 于 2013-3-20 11:33 编辑
garyliyong 发表于 2013-3-18 19:38
其实就是判断一下当前的drawable已经有交点了,就不需要再计算了。在这个函数里面有个求交器,主要是遍 ...


您好,大体修改思路我了解了。首先,最后std::copy()是将碰撞后的所有交点全存入进一个容器,这一步我并不需要,剩下的只要判断出是否模型中的drawable发生碰撞即可,也就是说哪怕碰到了房檐,我都算作是这个模型整体被框选上。

我改了一下,但是效果不好,您帮我看一下哪里改错了?

void NewPolytopeIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg:rawable* drawable)
{
        if (reachedLimit()) return;

        if ( !_polytope.contains( drawable->getBound() ) ) return;

        osg::TemplatePrimitiveFunctor<olytopeIntersectorUtils:olytopePrimitiveIntersector> func;
        func.setPolytope( _polytope, _referencePlane );
        func.setDimensionMask( _dimensionMask );
        func.setLimitOneIntersection( _intersectionLimit == LIMIT_ONE_PER_DRAWABLE || _intersectionLimit == LIMIT_ONE );

        drawable->accept(func);

        if (!(func.intersections.empty()))
        {
                PolytopeIntersectorUtils::Intersections::const_iterator it=func.intersections.begin();  //只插入一个intersection即可

                const PolytopeIntersectorUtils::PolytopeIntersection& intersection = *it;

                Intersection hit;
                hit.distance = intersection._distance;
                hit.maxDistance = intersection._maxDistance;
                hit.primitiveIndex = intersection._index;
                hit.nodePath = iv.getNodePath();
                hit.drawable = drawable;
                hit.matrix = iv.getModelMatrix();

                osg::Vec3 center;
                for (unsigned int i=0; i<intersection._numPoints; ++i)
                {
                        center += intersection._points;
                }
                center /= float(intersection._numPoints);
                hit.localIntersectionPoint = center;

                hit.numIntersectionPoints = intersection._numPoints;
                //std::copy(&intersection._points[0], &intersection._points[intersection._numPoints],&hit.intersectionPoints[0]);

                insertIntersection(hit);

        }
}

该用户从未签到

发表于 2013-3-20 13:48:48 | 显示全部楼层
garyliyong 发表于 2013-3-18 19:38
其实就是判断一下当前的drawable已经有交点了,就不需要再计算了。在这个函数里面有个求交器,主要是遍 ...

上面是我改的源码部分,下面是我在自己的工程cpp中,涉及鼠标handle()事件中的代码,请您结合这两部分,给与我指点:
                  
                         osg::ref_ptr<NewPolytopeIntersector> intersector =new NewPolytopeIntersector(osgUtil::Intersector::WINDOW, xMin, yMin, xMax, yMax);

                          osgUtil::IntersectionVisitor iv( intersector.get() );


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

                        if ( intersector->containsIntersections() )
                        {       
                                for (NewPolytopeIntersector::Intersections::iterator hitr = intersector->getIntersections().begin(); hitr != intersector->getIntersections().end(); ++hitr)
                                {
                                        osg::NodePath &np = hitr->nodePath;

                                        for (osg::NodePath::iterator itr = np.begin(); itr != np.end(); itr++)
                                        {
                                                if (!(*itr)->getName().empty())
                                                {
                                                          createShaders2((*itr),true);  //凡是框选中的模型着色
                                               
                                                        //break;
                                                }
                                        }
                                }
                        }

该用户从未签到

发表于 2013-3-20 13:52:08 | 显示全部楼层
liuzhiyu123 发表于 2013-3-18 10:36
记录一下测试过的drawable,然后比较,就在这个函数中

之前看到您贡献的那个框选的demo,很经典~现在的效果是,鼠标开始框选,完后还要等待5秒吧,才能把三四个选中并高亮。。。而且有时模型多了就卡死,不是等待时间的事(7个模型一小时都不够)。。。可是我让源码中只存入一个intersection就可以了啊。。。求结合两个代码给与您的建议~

该用户从未签到

发表于 2013-3-20 16:41:02 | 显示全部楼层
fenma3422 发表于 2011-11-22 17:19
今天也遇到了框选效率问题,于是对PolytopeIntersecto源码进行分析,发现PolytopeIntersecto对一个drawable ...

您好,看到您最早也提出框选效率的见解,我试着采取您说的第一种,一旦遍历出相交的drawable,则不继续求点集。对于源代码中修改的部分如下:
void NewPolytopeIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg:rawable* drawable)
{
        if (reachedLimit()) return;

        if ( !_polytope.contains( drawable->getBound() ) ) return;

        osg::TemplatePrimitiveFunctor<olytopeIntersectorUtils:olytopePrimitiveIntersector> func;
        func.setPolytope( _polytope, _referencePlane );
        func.setDimensionMask( _dimensionMask );
        func.setLimitOneIntersection( _intersectionLimit == LIMIT_ONE_PER_DRAWABLE || _intersectionLimit == LIMIT_ONE );

        drawable->accept(func);

        if (!(func.intersections.empty()))
        {
                std::cout<<drawable->getName()<<std::endl;   //输出碰撞得到的每个drawable名称

                createShaders2(drawable,true);           //对于碰撞的部分用着色器语言着红色
        }
}

但是效果请您看下:
未命名.jpg
图中,通过框选,可以立刻打印出碰撞的drawable名字,但拉矿完后,屏幕定住,没有着色,更不能在场景中动。。。也没错误,也没异常。。。请您给一些建议吧~

该用户从未签到

 楼主| 发表于 2013-3-20 17:53:20 | 显示全部楼层
本帖最后由 garyliyong 于 2013-3-20 17:55 编辑
mxl12315 发表于 2013-3-20 11:00
您好,大体修改思路我了解了。首先,最后std::copy()是将碰撞后的所有交点全存入进一个容器,这一步我并 ...


  if (reachedLimit()) return;

        if ( !_polytope.contains( drawable->getBound() ) ) return;

        osg::TemplatePrimitiveFunctor<olytopeIntersectorUtilslytopePrimitiveIntersector> func;
        func.setPolytope( _polytope, _referencePlane );
        func.setDimensionMask( _dimensionMask );
        func.setLimitOneIntersection( _intersectionLimit == LIMIT_ONE_PER_DRAWABLE || _intersectionLimit == LIMIT_ONE );

       在这个函数最上面的osg::TemplatePrimitiveFunctor所有涉及到的()函数里开始处if (_limitOneIntersection && !intersections.empty()) return; 改成if (!intersections.empty()) return;
        drawable->accept(func);

        if (!(func.intersections.empty()))
        {
                PolytopeIntersectorUtils::Intersections::const_iterator it=func.intersections.begin();  //只插入一个intersection即可

                const PolytopeIntersectorUtils:olytopeIntersection& intersection = *it;

                Intersection hit;
                //hit.distance = intersection._distance;
                //hit.maxDistance = intersection._maxDistance;
               // hit.primitiveIndex = intersection._index;

                hit.nodePath = iv.getNodePath();
                // hit.drawable = drawable;
               // hit.matrix = iv.getModelMatrix();

                //osg::Vec3 center;
                ///for (unsigned int i=0; i<intersection._numPoints; ++i)
               // {
                //        center += intersection._points;
               // }
               // center /= float(intersection._numPoints);
                //hit.localIntersectionPoint = center;

               // hit.numIntersectionPoints = intersection._numPoints;
                //std::copy(&intersection._points[0], &intersection._points[intersection._numPoints],&hit.intersectionPoints[0]);


                insertIntersection(hit);

该用户从未签到

发表于 2014-4-23 14:02:30 | 显示全部楼层
void PolytopeIntersector::intersect(osgUtil::IntersectionVisitor& iv, osg:rawable* drawable)
{
    if (reachedLimit()) return;

    if ( !_polytope.contains( drawable->getBound() ) ) return;

    osg::TemplatePrimitiveFunctor<olytopeIntersectorUtils:olytopePrimitiveIntersector> func;
    func.setPolytope( _polytope, _referencePlane );
    func.setDimensionMask( _dimensionMask );
    func.setLimitOneIntersection( _intersectionLimit == LIMIT_ONE_PER_DRAWABLE || _intersectionLimit == LIMIT_ONE );

    drawable->accept(func);

   /* if (func.intersections.empty()) return;*/

        if (!(func.intersections.empty()))
        {
                PolytopeIntersectorUtils::Intersections::const_iterator it=func.intersections.begin();  //只插入一个intersection即可

                const PolytopeIntersectorUtils::PolytopeIntersection& intersection = *it;

           /* for(PolytopeIntersectorUtils::Intersections::const_iterator it=func.intersections.begin();
                        it!=func.intersections.end();
                        ++it)
                {
                        const PolytopeIntersectorUtils::PolytopeIntersection& intersection = *it;*/

        Intersection hit;
        hit.distance = intersection._distance;
        hit.maxDistance = intersection._maxDistance;
        hit.primitiveIndex = intersection._index;
        hit.nodePath = iv.getNodePath();
        hit.drawable = drawable;
        hit.matrix = iv.getModelMatrix();

        PolytopeIntersectorUtils::Vec3_type center;
        for (unsigned int i=0; i<intersection._numPoints; ++i)
        {
            center += intersection._points[i];
        }
        center /= PolytopeIntersectorUtils::value_type(intersection._numPoints);
        hit.localIntersectionPoint = center;

        hit.numIntersectionPoints = intersection._numPoints;
        std::copy(&intersection._points[0], &intersection._points[intersection._numPoints],
              &hit.intersectionPoints[0]);

        insertIntersection(hit);
    }

该用户从未签到

发表于 2014-4-23 14:03:03 | 显示全部楼层
以上代码即可实现框选效率的提升

该用户从未签到

发表于 2014-7-1 16:22:55 | 显示全部楼层
大家有没有遇到这样 的问题:进入三维透视观察视角的时候进行拉框选取,不在框内的的目标选被选中,不在框内的目标选中。

该用户从未签到

 楼主| 发表于 2014-8-15 11:11:36 | 显示全部楼层
xiaol_deng 发表于 2014-7-1 16:22
大家有没有遇到这样 的问题:进入三维透视观察视角的时候进行拉框选取,不在框内的的目标选被选中,不在框 ...

这个目前没有遇到过

该用户从未签到

发表于 2014-8-28 20:36:01 | 显示全部楼层
garyliyong 发表于 2014-8-15 11:11
这个目前没有遇到过

该用户从未签到

发表于 2015-7-16 17:58:10 | 显示全部楼层
为什么 我重写 这个 intersect 方法之后   这个函数都不执行  我是继承的PolytopeIntersector。。。
osgUtil::IntersectionVisitor iv(picker);
用viewer->getCarmera()->accept(iv);  你们是怎么重写这个函数的啊  一个模型 求出来  那么多交点  晕死

该用户从未签到

发表于 2015-12-18 12:01:30 | 显示全部楼层
freesource1 发表于 2015-7-16 17:58
为什么 我重写 这个 intersect 方法之后   这个函数都不执行  我是继承的PolytopeIntersector。。。
osgU ...

今天刚做完框选效率的问题,呵呵,5个月了 你应该解决了吧

该用户从未签到

发表于 2015-12-22 22:42:49 | 显示全部楼层
晓风残月 发表于 2015-12-18 12:01
今天刚做完框选效率的问题,呵呵,5个月了 你应该解决了吧

隔了一段时间 没弄这个了  你可以把你框选的例子发给我嘛  

该用户从未签到

发表于 2015-12-23 14:22:56 | 显示全部楼层
freesource1 发表于 2015-12-22 22:42
隔了一段时间 没弄这个了  你可以把你框选的例子发给我嘛

wo 代码就是论坛上弄的。。没改,也没出问题。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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