osgimpostor例子

来源:互联网 发布:淘宝搭配套餐链接转换 编辑:程序博客网 时间:2024/05/16 00:53
本例子演示了impostor代替节点的应用。
以下是转自网上翻译源码的内容:
Impostor是一种LOD组节点,它既允许通过子结点到视点的距离来选择相应的子结点,又可以通
过到视点的距离来选择图片缓存。Impostor的原理是:通过缓存几何体(realgeometry)的图像
,然后在之后的帧内使用该图像代替该几何体。这有点像Billboard,但是, 它是实时更新并与
视点的位置相关的。通过映射了该纹理的四边形,可以降低场景的复杂度以提高性能。OSG中的
impostor并不是完全按照上述网址中的技术来实现的,但是这应该是个不错的开始。OSG的
Impostor结点远没有那么复杂,因为使用时你并不需要重构(重新组织)你的整个场景。你所要
做的就是为Impostor结点的每一个子结点设置相应的LOD可见范围值(visiblerange value),
并且设置一个Impostor阈值,来告诉渲染器(renderer)在什么距离以外应该使用Impostor的图
像缓存。osg::CullVisitor会自动处理所有的渲染前期(pre-renderingstages)的设置,计算
出所需的ImpostorSprites(这个类封装了图像缓存与四边形),并随视点的变化更新它们。如
果你使用osg::SceneView/CullVisitor,所有为了支持Impostor的复杂过程都会被很好的隐藏。
关于Impostor还有很多改进计划:
1) 估计一个ImpostorSprite在多少帧内会被重用,如果被重用的次数不会多于一个最小阈值的
话,就不创建这个ImpostorSprite而是直接使用几何体
2)与内存中的纹理共享数据
3)对ImpostorSprite使用简单的3D几何体而不是Billboard
4)减小ImpostorSprite的大小使之更适合内在的(underlying)几何体
Impostor继承自LOD,我们都知道LOD实现在指定范围内显示物体,Switch节点可以开关节点,这
些是怎么实现的呢,我们进入源码看看究竟。
virtual void traverse(NodeVisitor& nv);每个类型的节点当访问它的时候,都会进行递归调
用,而递归的关键就是traverse。
void Group::traverse(NodeVisitor& nv)
{
    for(NodeList::iterator 

itr=_children.begin();
        itr!=_children.end();
        ++itr)
    {
(*itr)->accept(nv);
    }
}
这是Group的递归,直接遍历所有的子节点。
再来看看LOD的递归调用,
for(unsigned int i=0;i<numChildren;++i)
            {    
                if 
(_rangeList[i].first<=required_range && required_range<_rangeList[i].second)
         
       {
                    _children[i]->accept(nv);
                }
            }
是的,判断了该节点是否在指定的视野内,如果不在就不进行递归调用,这样在osg中无论是更
行回调、事件回调、裁切回调,包括自己实现的回调,都会进行判断,不在视野内就忽略。
而在Impostor中的traverse呢,通过ImpostorSprite创建图片代替,在createImpostorSprite这
个函数中实现具体的图片创建过程,通过帧缓存对象,把节点选择到纹理中。
回到例子中,CreateHouses()创建了一个房子模型,加入到nodes中,LayoutAsGrid()函数通过
代替节点加入400个模型,
osgSim::Impostor * impostor = new osgSim::Impostor();
            impostor-
>setImpostorThreshold(static_cast<float> (Threshold));
            impostor-
>addChild(groups[i]);
            impostor->setRange(0, 0.0f, 1e7f);
         
impostor->setCenter(groups[i]->getBound().center());
设置代替节点的参数。
TestManipulator继承CameraManipulator,测试的操作器。写自己的操作器只需重写几个类就可
以实现,
 /** set the position of the matrix manipulator using a 4x4 Matrix.*/
        virtual 
void setByMatrix(const osg::Matrixd& matrix);
        /** set the position of the 
matrix manipulator using a 4x4 Matrix.*/
        virtual void setByInverseMatrix
(const osg::Matrixd& matrix) { setByMatrix(osg::Matrixd::inverse(matrix)); 
/** get the position of the manipulator as 4x4 Matrix.*/
        virtual osg::Matrixd 
getMatrix() const;
        /** get the position of the manipulator as a inverse 
matrix of the manipulator, typically used as a model view matrix.*/
        virtual 
osg::Matrixd getInverseMatrix() const;
最重要的是getInverseMatrix这个函数,osg中每一帧的更新回调会调用操作器的这个函数赋值
给相机,实现相机的更新。
virtual void setNode(osg::Node*);
/** Move the camera to the default position. 
            May be ignored by 
manipulators if home functionality is not appropriate.*/
        virtual void home
(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us);
      
        /** 
Start/restart the manipulator.*/
        virtual void init(const 
osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us);
        /** handle events, 
return true if handled, false otherwise.*/
        virtual bool handle(const 
osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us);
这几个函数在重写的时候也经常用到,设置中心节点,初始位置、初始化,事件处理。
原创粉丝点击