查看: 2432|回复: 5

关于PagedLOD加载子节点的问题

[复制链接]

该用户从未签到

发表于 2009-12-22 14:45:43 | 显示全部楼层 |阅读模式
本帖最后由 lucifinil 于 2009-12-22 14:57 编辑

PagedLOD节点的包围核是怎算的,在哪算的?是根据所选择的子节点的包围核算的吗?也就是说根据视点的不同,包围核也不一样?是在DatabasePager:atabaseThread::run把子节点内容加载到内存后算的吧?

该用户从未签到

发表于 2009-12-22 15:10:25 | 显示全部楼层
通常我们是使用setCenter()和setRadius()来预先设置PagedLOD的包围体中心和半径,例如VPB就是这样构建四叉树的;否则的话,系统将自动根据子节点的包围体进行计算。而后者的机制却通常不适合动态加载。

该用户从未签到

 楼主| 发表于 2009-12-22 15:22:42 | 显示全部楼层
2# array

谢谢array.
我也觉得奇怪。
源码中
void CullVisitor::apply(LOD& node)
{
    if (isCulled(node)) return;
    // push the culling mode.
    pushCurrentMask();
    // push the node's state.
    StateSet* node_state = node.getStateSet();
    if (node_state) pushStateSet(node_state);
    handle_cull_callbacks_and_traverse(node);
    // pop the node's state off the render graph stack.   
    if (node_state) popStateSet();
    // pop the culling mode.
    popCurrentMask();
}
如果没有包围核isCulled(node),没法做啊。而加载子节点是在这个函数后面,在handle_cull_callbacks_and_traverse(node)中,所以觉得动态加载子节点算包围核,是不能实现的。

该用户从未签到

 楼主| 发表于 2009-12-22 15:32:15 | 显示全部楼层
还有一个问题想问,还是加载子节点的问题,加载子节点使用的是什么机制?在void PagedLOD::traverse(NodeVisitor& nv)中

        for(unsigned int i=0;i<_rangeList.size();++i)
            {
                if (_rangeList[i].first<=required_range && required_range<_rangeList[i].second)
                {
                    if (i<_children.size())
                    {
                        if (updateTimeStamp)
                        {
                            _perRangeDataList[i]._timeStamp=timeStamp;
                            _perRangeDataList[i]._frameNumber=frameNumber;
                        }

                        _children[i]->accept(nv);
                        lastChildTraversed = (int)i;
                    }
                    else
                    {
                        needToLoadChild = true;
                    }
                }
            }

            if (needToLoadChild)
            {
                unsigned int numChildren = _children.size();

                // select the last valid child.
                if (numChildren>0 && ((int)numChildren-1)!=lastChildTraversed)
                {
                    if (updateTimeStamp)
                    {
                        _perRangeDataList[numChildren-1]._timeStamp=timeStamp;
                        _perRangeDataList[numChildren-1]._frameNumber=frameNumber;
                    }
                    _children[numChildren-1]->accept(nv);
                }

                // now request the loading of the next unloaded child.
                if (nv.getDatabaseRequestHandler() && numChildren<_perRangeDataList.size())
                {
                    // compute priority from where abouts in the required range the distance falls.
                    float priority = (_rangeList[numChildren].second-required_range)/(_rangeList[numChildren].second-_rangeList[numChildren].first);

                    // invert priority for PIXEL_SIZE_ON_SCREEN mode
                    if(_rangeMode==PIXEL_SIZE_ON_SCREEN)
                    {
                        priority = -priority;
                    }

                    // modify the priority according to the child's priority offset and scale.
                    priority = _perRangeDataList[numChildren]._priorityOffset + priority * _perRangeDataList[numChildren]._priorityScale;

                    if (_databasePath.empty())
                    {
                        nv.getDatabaseRequestHandler()->requestNodeFile(_perRangeDataList[numChildren]._filename,this,priority,nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest);
                    }
                    else
                    {
                        // prepend the databasePath to the child's filename.
                        nv.getDatabaseRequestHandler()->requestNodeFile(_databasePath+_perRangeDataList[numChildren]._filename,this,priority,nv.getFrameStamp(), _perRangeDataList[numChildren]._databaseRequest);
                    }
                }

    为什么numChildren = _children.size()就是需要加载的节点了,好像节点加载进来也没把nv传下去啊?
翻阅了《最长的一帧》,《OSG编程入门指南》以及新书《三维渲染引擎设计与实践》都没对pagdlod节点加载机制的解释,array能不能通过这段代码解释一下吗?有人说OSG默认从最低精度的LOD开始读取,不管初始位置。对每个pagedlod将其所有级别LOD均加载进来。同时数据管理线程及时移除不活动节点(超过一定时间未访问)。是这样吗?

该用户从未签到

发表于 2009-12-22 16:04:06 | 显示全部楼层
“对每个pagedlod将其所有级别LOD均加载进来。同时数据管理线程及时移除不活动节点”,这种说法完全错误!

OSG的PagedLOD对于子节点的管理较为严格,即,第0个子节点必须是最粗糙一级,而最后一个子节点是最精细一级。在此前提下,每当子节点范围符合条件时,都会自动使用requestNodeFile申请下一个子节点。除非所有的子节点都已经加载进来,或者所有未加载的节点都不在当前可视范围内

总之,PagedLOD的内部实现代码没有什么难读的,因此也不必介绍什么,您一行一行去看,想必可以看懂
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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