查看: 2188|回复: 3

如何实现地形对包络体的遮挡效果?

[复制链接]

该用户从未签到

发表于 2011-11-8 13:05:18 | 显示全部楼层 |阅读模式
本帖最后由 口口广大 于 2011-11-8 13:24 编辑


osg有个例子如下图,实现了包络体SphereSegment.与地形模型相切。

抓图1.png


想实现一个更复杂的效果,即是在生成包络体时,判断地形有否遮挡住该包络体,最后只生成该包络体未被地形遮蔽的部分。

想想原理很简单,查看SphereSegment.cpp,在画surfac的PowerSphereSegment::Surface_drawImplementation源码如下
  1. for(int i=0; i+1<=_density; i++)
  2.             {
  3.                 // Because we're drawing quad strips, we need to work out
  4.                 // two azimuth values, to form each edge of the (z-vertical)
  5.                 // strips
  6.                 float az1 = _azMin + (i*azIncr);
  7.                 float az2 = _azMin + ((i+1)*azIncr);

  8.                 glBegin(GL_QUAD_STRIP);
  9.                 for (int j=0; j<=_edensity; j++)
  10.                 {
  11.                     float elev = _elevMin + (j*elevIncr);

  12.                     // QuadStrip Edge formed at az1
  13.                     // ----------------------------

  14.                     // Work out the sphere normal
  15.                     float x = cos(elev)*sin(az1);
  16.                     float y = cos(elev)*cos(az1);
  17.                     float z = sin(elev);

  18.                     glNormal3f(-x, -y, -z);               
  19.                     glVertex3f(_centre.x() + _radius*x,
  20.                             _centre.y() + _radius*y,
  21.                             _centre.z() + _radius*z);
  22.                           
  23.                     // QuadStrip Edge formed at az2
  24.                     // ----------------------------

  25.                     // Work out the sphere normal
  26.                     x = cos(elev)*sin(az2);
  27.                     y = cos(elev)*cos(az2);
  28.                     // z = sin(elev);   z doesn't change

  29.                     glNormal3f(-x, -y, -z);
  30.                     glVertex3f(_centre.x() + _radius*x,
  31.                             _centre.y() + _radius*y,
  32.                             _centre.z() + _radius*z);
  33.                 }
  34.                 glEnd();
  35.             }
  36.           }
复制代码
无非将方位角与俯仰角划分成i*j份,然后每一份根据某个数学公式算出两个点,然后连起来即可。

那么我想有个简单的办法,即判断每一份两点的连线与地形模型是否有交,如果有交就退出当层循环,那么最后画出的片面应该就是未被地形遮挡的片面。


问题就是不知道如何写线段与地形模型相交的函数,呵呵。写了试试如下

  1. int PowerSphereSegment::computeIntersectionTerrain(osg::Vec3d& start,osg::Vec3d& end)
  2. {
  3.   int result = 0;

  4.    osgUtil::IntersectVisitor ivXY;
  5.    osg::ref_ptr<osg::LineSegment> lineXY = new osg::LineSegment(start,end);
  6.    ivXY.addLineSegment(lineXY.get());
  7.       _terrainNode->accept(ivXY);

  8.     if (ivXY.hits())
  9.    {
  10.                 osgUtil::IntersectVisitor::HitList& hitList = ivXY.getHitList(lineXY.get());
  11.                 std::cout<<"  hitList SIZE = "<<hitList.size()<<std::endl;
  12.    
  13.                 result =  hitList.size();
  14.     }

  15.          return 0;
  16. }
复制代码
执行时报警告如下
Warning: invalid line segment passed to IntersectVisitor::addLineSegment(..)
         0 0 0 0 0 0 segment ignored..

不知有何问题?而且我感觉这个osg::Vec3d& start,osg::Vec3d& end是该包络体的局部坐标系,而地形模型则是另一个局部坐标系,两个不同坐标系下的几何体能否直接相交?是不是要矩阵变化什么的的?谢谢!

该用户从未签到

发表于 2011-11-8 15:15:43 | 显示全部楼层
写线段与地形模型相交的函数

用osgUtil:ineSegmentIntersector

该用户从未签到

 楼主| 发表于 2011-11-8 23:03:21 | 显示全部楼层
本帖最后由 口口广大 于 2011-11-8 23:38 编辑
liushui 发表于 2011-11-8 15:15
写线段与地形模型相交的函数

用osgUtil:ineSegmentIntersector


谢谢,利用osgUtil:ineSegmentIntersector改写了求交函数

  1. int PowerSphereSegment::computeIntersectionTerrain(osg::Vec3d& start,osg::Vec3d& end)
  2. {
  3. osgUtil::LineSegmentIntersector::Intersections _intersections;
  4. osg::ref_ptr< osgUtil::LineSegmentIntersector > _lineSegmentIntersector = new osgUtil::LineSegmentIntersector(start,end);
  5. osgUtil::IntersectionVisitor _iv(_lineSegmentIntersector.get());
  6. _terrainNode->accept(_iv);
  7. _intersections=_lineSegmentIntersector->getIntersections();
  8. return_intersections.size();        
  9. }
复制代码
最后返回的结果始终是0个交点,我想问题可能是传入的osg::Vec3d& start,osg::Vec3d& end点是该包罗体的局部坐标,是不是需要先求出这两个点的世界坐标才能用ineSegmentIntersector求交点?


如果利用osg::computeLocalToWorld函数求世界坐标,一般来说要用一个NodeVisitor。该访问器类用于返回某个节点的世界坐标, 它从起始节点开始向父节点遍历,并随时将历经的节点记录到nodePath中。
,第一次到达根节点之后,它将记录起始节点的世界坐标。连结起始节点到根节点路径上的 ,所有矩阵之后,即可获得节点的世界坐标。


这时仿佛有个矛盾。矛盾就是一般的思路是我先生成这个包罗体以后,然后通过旋转、缩放、平移矩阵将它加载到世界坐标系下,此时通过NodeVisitor能获得根节点路径。而我此刻在PowerSphereSegment::Surface_drawImplementation中调用 computeIntersectionTerrain函数时,我的包罗体尚未加载任何旋转矩阵,也就是还未有任何到父节点的路径,那么我此时该如何求包罗体两点的世界坐标?谢谢!

该用户从未签到

发表于 2011-11-9 11:34:38 | 显示全部楼层
不矛盾,比如碰撞检测,你向前移动一个步长,是要首先判断前面是否有障碍物,如果有计算可以移动的距离等等,算好了预期位置之后,再把自己的位置放到那里。

我想是一回事
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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