查看: 2493|回复: 19

模型碰撞检测问题(请array老师看看)

[复制链接]

该用户从未签到

发表于 2011-3-16 23:44:54 | 显示全部楼层 |阅读模式
各位大侠,请教一个问题:

现有一个很大的flt模型文件,我需要与这个模型中的一些按钮做碰撞检测,有办法得到这些按钮的包围盒吗?或者根本不需要求包围盒,有什么更好的办法么?

该用户从未签到

发表于 2011-3-17 08:52:54 | 显示全部楼层
您不妨直接进行求交测试,在nodePath中判断是否存在这些按钮节点

或者您可以通过ComputeBoundsVisitor来计算节点的包围盒

该用户从未签到

 楼主| 发表于 2011-3-17 10:58:42 | 显示全部楼层
回复 1# haoshuang3394


    谢谢array老师的建议,我去试试。有问题再请教您!

该用户从未签到

 楼主| 发表于 2011-3-17 22:48:05 | 显示全部楼层
回复 2# array


    array老师,现在基本上能够得到模型的包围盒了,但是有一个问题,我想得到某一个object的包围盒时,总是略过检查object的名称,直接检查面片了。
注:我用了findNodeVisitor类,此类的作用是根据节点的名称来找到该节点的指针列表。下面是creator下建的一个测试模型test.flt的层次图:
creator层次图.jpg
我debug了一下如下代码,发现程序直接跳过o260和o339的检查。
主要代码如下:
  1. osg::ref_ptr<osg::Node> root=osgDB::readNodeFile("test.flt");
  2.         osg::ref_ptr<osg::Group> group=new osg::Group;
  3.         group=root->asGroup();
  4.         findNodeVisitor findNode("o260");
  5.         group->accept(findNode);
  6.        
  7.         for (std::vector<osg::Node*>::reverse_iterator itr=findNode.getNodeList().rbegin();
  8.                 itr != findNode.getNodeList().rend(); ++itr)
  9.         {
  10.                 osg::ComputeBoundsVisitor bv;
  11.                 (*itr)->accept(bv);
  12.                 osg::BoundingBox bb1;
  13.                 bb1=bv.getBoundingBox();
  14.                 std::cout<<"the node's name: "<<(*itr)->getName()<<std::endl;
  15.                 std::cout<<bb1.xMin()<<" "<<bb1.yMin()<<" "<<bb1.zMin()<<std::endl
  16.                         <<bb1.xMax()<<" "<<bb1.yMax()<<" "<<bb1.zMax()<<std::endl;
  17.         }
复制代码
另外,如果我直接查找p18,则可以打印出p18的包围盒,可这不是我想要的,求助!

该用户从未签到

发表于 2011-3-18 08:21:27 | 显示全部楼层
我不明白您的意思?您遇到了什么问题??

该用户从未签到

 楼主| 发表于 2011-3-18 09:33:15 | 显示全部楼层
回复 5# array


    我的意思很简单,我想得到某一个object(如o260)的包围盒,但是我在遍历整个层次图的时候,
程序没有检查o260这个节点,而是直接检查o260的子节点p18,请问这有可能是怎么造成的呢?

该用户从未签到

发表于 2011-3-18 10:58:49 | 显示全部楼层
这恐怕只能是您自己的代码造成的……

该用户从未签到

 楼主| 发表于 2011-3-18 11:57:18 | 显示全部楼层
回复 7# array


    谢谢啦,我再检查检查代码。

该用户从未签到

发表于 2011-3-18 14:21:23 | 显示全部楼层
为何不把需要碰撞检测的按钮单独拉出来呢

该用户从未签到

 楼主| 发表于 2011-3-18 21:10:45 | 显示全部楼层
回复 9# tianxiao888


    谢谢您的建议,不过我不太明白您这句话的意思,能具体说说么?您的意思是我把需要碰撞的节点作为db的直接子节点么?

该用户从未签到

 楼主| 发表于 2011-3-19 00:13:57 | 显示全部楼层
谢谢array和tianxiao888,我已经知道问题的所在了:在creator中可以操作的节点为Transform节点,我们不能直接操作Transform节点的子节点。在这个例子中,我们不能直接操作o260,因为它不是Transform节点,它的Transform节点是g2。所以tianxiao888的建议很不错,谢谢。

该用户从未签到

发表于 2011-3-21 09:30:12 | 显示全部楼层
您可能还需要检查下您的程序,因为如果您理解的意思是“除了transform节点,其他节点在遍历时是找不到的话”,那么这其实是不正确的。

该用户从未签到

发表于 2011-3-21 09:55:22 | 显示全部楼层
嗯,我的意思是按钮做为单独的模型,跟主体独立出来

该用户从未签到

 楼主| 发表于 2011-3-21 16:45:51 | 显示全部楼层
回复 12# aya_daxiang


    我并没有说这句话。我的意思是object节点在Creator中本身就不是一个单独的变换单位,需要配合group一起使用。

该用户从未签到

发表于 2011-3-21 17:37:35 | 显示全部楼层
嗯,我加引号只是为了强调下,并不是说那时您的原话,不好意思了。我得加强下标点符号的运用了
我只是想说您如果找不到o260和o339的话,原因应该是您程序的问题。

该用户从未签到

 楼主| 发表于 2011-3-22 09:55:32 | 显示全部楼层
回复 15# aya_daxiang


    我不知道您导过flt格式的模型没有,我这儿写了程序试了一下,如果您有时间,请帮忙看看,程序的问题出在哪儿,为什么只能找到g232,而不能找到o232?
程序代码不多,我用的是vs2008,include路径和library目录可能需要改一下,findNodeVisitor.h和findNodeVisitor.cpp没有贴出来,我没办法上传附件!!!

  1. #include <osgDB/ReadFile>
  2. #include <osgViewer/Viewer>
  3. #include <osg/ComputeBoundsVisitor>

  4. #include "findNodeVisitor.h"
  5. #include <iostream>

  6. int main(int argc,char** argv)
  7. {
  8.         osgViewer::Viewer viewer;
  9.         osg::ref_ptr<osg::Node> root=osgDB::readNodeFile("test2.flt");

  10. /* Test: just get the boundingbox of the whole model*/
  11.         osg::ComputeBoundsVisitor boundvisitor;
  12.         root->accept(boundvisitor);
  13.         osg::BoundingBox bb;
  14.         bb=boundvisitor.getBoundingBox();
  15.         std::cout<<"root's name: "<<root->getName()<<std::endl;
  16.         std::cout<<bb.xMin()<<" "<<bb.yMin()<<" "<<bb.zMin()<<std::endl
  17.                 <<bb.xMax()<<" "<<bb.yMax()<<" "<<bb.zMax()<<std::endl;

  18. /* get the specified node's bounding box */
  19.         osg::ref_ptr<osg::Node> node=new osg::Node;
  20.         osg::ref_ptr<osg::Group> group=new osg::Group;
  21.         group=root->asGroup();

  22.         //您能找到o232这个模型么?
  23.         findNodeVisitor findNode("g232");
  24.         group->accept(findNode);
  25.        
  26.         for (std::vector<osg::Node*>::iterator itr=findNode.getNodeList().begin();
  27.                 itr != findNode.getNodeList().end(); ++itr)
  28.         {
  29.                 osg::ComputeBoundsVisitor bv;
  30.                 (*itr)->accept(bv);
  31.                 osg::BoundingBox bb1;
  32.                 bb1=bv.getBoundingBox();
  33.                 std::cout<<"the node's name: "<<(*itr)->getName()<<std::endl;
  34.                 std::cout<<bb1.xMin()<<" "<<bb1.yMin()<<" "<<bb1.zMin()<<std::endl
  35.                         <<bb1.xMax()<<" "<<bb1.yMax()<<" "<<bb1.zMax()<<std::endl;
  36.         }

  37.         viewer.setSceneData(root);

  38.         return viewer.run();
  39. }
复制代码

该用户从未签到

发表于 2011-3-22 12:05:40 | 显示全部楼层
恩,你要找的“o232"或者"g232",这个名字是从哪里看到的?creator里面吗?如果你使用osgconv讲.flt转换成.osg或者 .ive的话,.ive/osg里面节点名称可能与.flt文件里不同,解决办法你可以看看这里http://www.mail-archive.com/osg- ... h.org/msg37212.html
我刚才试了试NPS tutorial 用到的"t72-tank_des.flt", 在setting OSG_OPTIMIZER to off 之后,osgconv 得到的osg模型里面节电的名称看起来就是正确的了 .

该用户从未签到

 楼主| 发表于 2011-3-22 22:58:33 | 显示全部楼层
回复 17# aya_daxiang


    谢谢您的意见,不过这个链接我打不开啊。另外,osgconv将flt模型转化为.ive或者.osg之后,是否能够满足我的要求,我得试一试,再来与您讨论。

该用户从未签到

发表于 2011-3-23 09:21:14 | 显示全部楼层
啊,这么说你并没有将flt转换成.ive或是.osg是么?这样的话那个连接里面说的情况就不适用于您的问题了。先前我还以为是转换时导致了节点名称改变,所以才找不到。如果你确定节点名称正确的话,(比如你的第一个例子o260及子节点p18,可以打印出p18节电的parentNode的名称,看是否是“o260"),我觉得如果方便的话上传一下你用的模型把,你的程序我觉得没什么大问题。

之前拿个连接有兴趣地可以去osg mailist里面搜索“node names not preserved going from flt to ive/osg“

该用户从未签到

 楼主| 发表于 2011-3-23 21:08:29 | 显示全部楼层
回复 19# aya_daxiang


    今天用osgconv把test2.flt转换成了test2.ive,在程序里面试了一下,发现仍然没有找到o232节点,所以估计是creator的原因。
抱歉,上次试图上传整个工程的,发现只能上传图片,郁闷。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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