|
前沿:
1、这个问题以前在一个帖子里也问过,不过最终并没有得到解决,为了突出问题的核心,我将不必要的东西简化了。我把问题、现象和我的思考贴在下面,大侠们给指点指点;
2、发这个帖子也费了点力气,谢谢各位的真诚帮助。
一、问题:利用osg::ComputeBoundsVisitor返回的包围盒究竟是整个全局世界坐标系(也就是root根节点的坐标系)下的包围盒,还是在待求节点的父节点坐标系下的包围盒?
二、已做工作:
1、array在已前的帖子中确定一定以及肯定地告诉我,肯定返回的是以root根节点坐标系为基准的包围盒,因为他一直这么用没有问题;
2、array说,他一般不用PAT节点,而用MatrixTransform节点来设置节点的旋转、平移等操作;
3、利用osg::ComputeBoundsVisitor求包围盒的代码如下(应该是对的吧。。)
osg::ComputeBoundsVisitor boundvisitor;
head->accept(boundvisitor);//head是读进来的一个节点
osg::BoundingBox bb;
bb = boundvisitor.getBoundingBox();
三、代码及现象描述:
1、我的场景结构非常简单,如图
有些部分解释下:整个树的左支是主体,两个MT节点负责平移和放缩。树的右支是为了显示左边的head节点的包围盒用的,具体思路是这样,首先构造一个中心在(0,0,0)边长为1的box节点,然后根据head节点的包围盒bb中的相关信息去设置boxBounding节点的矩阵,这样的效果就是这个box的大小就是head包围盒的大小,位置也移到了head包围盒的中心位置,让他们同时在场景中显示。(为了显示清楚,我显示了head的线框模型,box的边线也加粗了)
2、重要代码及注释
//省略头文件
void main(void)
{//读入一个head模型,它是一个红色线框显示的正方体
osg::ref_ptr<osg::Node> head = osgDB::readNodeFile("head.flt");
//下面使这个head节点线框显示
osg::ref_ptr<osg:olygonMode> polymode= new osg::PolygonMode;
polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode:INE);
head->getOrCreateStateSet()->setAttributeAndModes(polymode.get(),osg::StateAttribute::ON);
head->getOrCreateStateSet()->setMode(GL_CULL_FACE,osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE);
//下面读入一个球,和head一样大小,用来示意位置
osg::ref_ptr<osg::Node> sphere = osgDB::readNodeFile("sphere.flt");
//下面定义一个mtAll节点,朝X正方向偏移,同时将那个sphere节点挂上去
osg::ref_ptr<osg::MatrixTransform> mtAll=new osg::MatrixTransform;
mtAll->setMatrix(osg::Matrix::translate(20,0,0));
mtAll->addChild(sphere.get());
//定义一个headTrans节点,再朝X正方向偏移,挂入head节点,同时将其本身挂到mtAll节点上去,树的左半边构建完毕
osg::ref_ptr<osg::MatrixTransform> headTrans=new osg::MatrixTransform;
headTrans->setMatrix(osg::Matrix::translate(20,0,0));//移动
headTrans->addChild(head.get());//将head节点挂上去
mtAll->addChild(headTrans.get());//将其本身挂到mtAll节点上去,树的左半边构建完毕
//计算head的包围盒
osg::ComputeBoundsVisitor boundvisitor;
headTrans->accept(boundvisitor);//用headTrans节点去接受这个访问器
osg::BoundingBox bb;
bb = boundvisitor.getBoundingBox();
//下面是构造场景树的右支,box是一个绿色粗线条显示的方体,代表包围盒
osg::ref_ptr<osg::MatrixTransform> boxBounding=new osg::MatrixTransform;
osg::ref_ptr<osg::Geode> box = new osg::Geode;
osg::ref_ptr<osg::ShapeDrawable> sd = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0f,0.0f,0.0f),1));
sd->setColor(osg::Vec4(0.0,1.0,0.0,1.0));//设置颜色绿色,好区别
osg::ref_ptr<osg::StateSet> state = sd->getOrCreateStateSet();
osg::ref_ptr<osg::PolygonMode> pm = new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
state->setAttributeAndModes(pm.get());//也设置线框模式
osg::ref_ptr<osg::LineWidth> lw =new osg::LineWidth(10.0);
state->setAttribute(lw.get());//设置线条粗细,看的清
box->addDrawable(sd.get());
boxBounding->addChild(box.get());
//下面就是将那个box按照head的包围盒来进行缩放和移动,以使得这个box刚好能表示包围盒所在位置
boxBounding->setMatrix(osg::Matrix::scale(bb.xMax()-bb.xMin(),bb.yMax()-bb.yMin(),bb.zMax()-bb.zMin())*osg::Matrix::translate(bb.center()));
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
osg::ref_ptr<osg::Group> root = new osg::Group;
root->addChild(mtAll.get());
root->addChild(boxBounding.get());
viewer->setCameraManipulator(new osgGA::TrackballManipulator);//漫游
viewer->setSceneData(root.get());
while (!viewer->done())
{
viewer->frame();
}
}
3、现象以及思考
运行结果如图所示:
分析:
(1)根据线框颜色很明显判别,左边的绿框是场景树的右枝,也就是说包围盒的位置和大小就应该在那儿;右边的红色的是head节点,确实平移了。
(2)很明显,这个包围盒(绿色的部分)并没有正确地包住head节点(红色线条的方体)。
思考:
(1)在接受访问器的时候我是用的headTrans这个节点接受的,因为我仅仅想获得head节点的包围盒,而不需要head+sphere整个节点的包围盒;我如果用mtAll这个节点去接受该访问器,就获得了整个的包围盒,这不是我要的结果,效果如图:
(2)从上面的效果看,我感觉用 osg::ComputeBoundsVisitor计算出的包围盒仅仅是以其父节点坐标系为基准,而不是以根节点为基准的,否则的话这样的代码应该能得到我要的效果。
(3)我如果仅仅想获得head节点的包围盒该怎么办呢?
/***************************************/
写了这么多,无非是想把问题描述清楚,也是按照问题、做实验、上代码的要求写的,望各位老师能够抽一点时间帮忙看下,在此一并感谢~~~ |
|