查看: 1527|回复: 4

利用线段求交做碰撞检测时,发现效果不正常,请各位指教下我的问题在哪里,谢谢

[复制链接]

该用户从未签到

发表于 2013-9-2 11:56:01 | 显示全部楼层 |阅读模式
先说下我的问题吧,我在osg中放了两个球movingNode,TargetNode。用movingNode向TargetNode移动,在前者的内部做一条以包围盒中心点和边界点为端点的线段,就用这条线段与TargetNode求交以做碰撞检测。
但是我发现明明两个球没有接触,就检测到碰撞了。
下面是我的一些代码
一个handler,控制小球移动,并每帧检测碰撞
  1. class PickHandler : public osgGA::GUIEventHandler {
  2. public:

  3.         PickHandler(){}

  4.           ~PickHandler() {}

  5.           bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa);

  6.        
  7. };

  8. bool PickHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
  9. {
  10.         switch(ea.getEventType())
  11.         {
  12.   
  13.         case(osgGA::GUIEventAdapter::KEYDOWN):
  14.                 {
  15.                         if (ea.getKey()=='1')
  16.                         {        
  17.                                 osg::Matrix d = mtl->getMatrix();
  18.                                 osg::Vec3 v = d.getTrans();
  19.                                 v.set(v.x()+0.5,v.y(),v.z());
  20.                                 d.setTrans(v);
  21.                                 mtl->setMatrix(d);
  22.                         }
  23.                         if (ea.getKey()=='2')
  24.                         {        
  25.                                 osg::Matrix d = mtl->getMatrix();
  26.                                 osg::Vec3 v = d.getTrans();
  27.                                 v.set(v.x()- 0.5,v.y(),v.z());
  28.                                 d.setTrans(v);
  29.                                 mtl->setMatrix(d);
  30.                         }
  31.                         return false;
  32.                 }   
  33.         case(osgGA::GUIEventAdapter::FRAME):
  34.                 {
  35.                        
  36.                        
  37.                         if (tankLocationSegment->containsIntersections())
  38.                         {
  39.                                
  40.                                 cout<<"1"<<endl;
  41.                         }
  42.                        
  43.                 }
  44.         default:
  45.                 return false;
  46.         }
  47. }
复制代码
一些全局变量
  1. osg::ref_ptr<osg::MatrixTransform> mtl;
  2. osg::ref_ptr<osg::MatrixTransform> mtr;
  3. osg::ref_ptr<osg::Geode> movingNode;
  4. osg::ref_ptr<osg::Geode> targetNode;

  5. osgUtil::IntersectionVisitor findTankElevationVisitor;
  6. osgUtil::LineSegmentIntersector* tankLocationSegment;
复制代码
主函数
  1. int _tmain(int argc, _TCHAR* argv[])
  2. {
  3.         osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
  4.         osg::ref_ptr<osg::Group> root = new osg::Group;
  5.        
  6.         mtl = new osg::MatrixTransform;
  7.         movingNode = new osg::Geode;
  8.         movingNode = createBall();
  9.         mtl->addChild(movingNode);
  10.         root->addChild(mtl);
  11.        
  12.         mtr = new osg::MatrixTransform;
  13.         mtr->setMatrix(osg::Matrix::translate(3.0,0.0,0.0));
  14.         targetNode = new osg::Geode;
  15.         targetNode = createBall();
  16.         mtr->addChild(targetNode);
  17.         root->addChild(mtr);
  18.         //
  19.        
  20.         osg::BoundingSphere bs = movingNode->getBound();
  21.         osg::Vec3 cen = bs.center();
  22.         osg::Vec3 edge = bs.center()+osg::Vec3(1.0f,0.0f,0.0f);
  23.        
  24.         tankLocationSegment = new osgUtil::LineSegmentIntersector(cen,edge);
  25.         findTankElevationVisitor.setIntersector(tankLocationSegment);

  26.         targetNode->accept(findTankElevationVisitor);
  27.        
  28.                //把用于碰撞检测的线画出来
  29.         osg::ref_ptr<osg::Geometry> line = new osg::Geometry;
  30.         osg::ref_ptr<osg::Vec3Array> lineVertices = new osg::Vec3Array;
  31.         line->setVertexArray(lineVertices.get());
  32.         lineVertices->push_back(cen);
  33.         lineVertices->push_back(edge);
  34.         line->addPrimitiveSet(new osg::DrawArrays(osg::DrawArrays::LINES,0,2));
  35.         osg::ref_ptr<osg::Geode> lineNode = new osg::Geode;
  36.         lineNode->addDrawable(line.get());
  37.         root->addChild(lineNode);
  38.        
  39.         viewer->setSceneData(root);
  40.         viewer->addEventHandler(new PickHandler());
  41.         viewer->run();
  42.         return 0;
  43. }
复制代码
两个球的位置,以及实际的那条线的位置
s1.png s2.png

该用户从未签到

 楼主| 发表于 2013-9-4 15:53:21 | 显示全部楼层
问题解决了 我自己说下吧
比如场景结构是
  1. root->addChild(mt);
  2. mt->addChild(node);
复制代码
其中mt是位置变换节点切不为单位阵,node是要碰撞检测的场景节点。
那么应该用
  1. mt->accept(_IntersectVisitor);
复制代码
而不是
  1. node->accept(_IntersectVisitor);
复制代码

该用户从未签到

 楼主| 发表于 2013-9-2 11:56:58 | 显示全部楼层
程序刚启动就会不停的提示碰撞了,请问下各位我的代码是哪里写错了吗? 多谢啊!

该用户从未签到

发表于 2013-9-2 12:41:05 | 显示全部楼层
是不是检测到的是你本身的球

该用户从未签到

 楼主| 发表于 2013-9-2 16:37:43 | 显示全部楼层
bigboy 发表于 2013-9-2 12:41
是不是检测到的是你本身的球

谢谢关注!
我打印了相交节点的名字,发现系统确实认为是和TargetNode相交了。

会不会是坐标系的问题呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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