osg 场景节点(事件,更新,裁剪)遍历状态开启机制
2018-02-23 15:07
381 查看
OSG 显示引擎为优化其显示效率,节点的更新遍历,事件处理遍历默认情况下是关闭的,内部通过更新计数来控制是否将事件处理,节点更新应用到子场景中。
void Node::setUpdateCallback(Callback* nc);
void Node::setEventCallback(Callback* nc);
void Node::setCullingActive(bool active);
下面我们看,新节点先加入到场景图中再设置回调函数 与 新节点设置回调函数再加入到场景图中 控制计数的改变有何不同:
a) 新节点先加入到场景图中再设置回调函数
新节点添加前没有设置回调函数:
然后设置回调函数:void Node::setUpdateCallback(Callback* nc)
{
// if no changes just return.
if (_updateCallback==nc) return;
// updated callback has been changed, will need to update
// both _updateCallback and possibly the numChildrenRequiringAppTraversal
// if the number of callbacks changes.
// update the parents numChildrenRequiringAppTraversal
// note, if _numChildrenRequiringUpdateTraversal!=0 then the
// parents won't be affected by any app callback change,
// so no need to inform them.
if (_numChildrenRequiringUpdateTraversal==0 && !_parents.empty())
{
int delta = 0;
if (_updateCallback.valid()) --delta;
if (nc) ++delta;
if (delta!=0)
{
// the number of callbacks has changed, need to pass this
// on to parents so they know whether app traversal is
// required on this subgraph.
for(ParentList::iterator itr =_parents.begin();
itr != _parents.end();
++itr)
{
(*itr)->setNumChildrenRequiringUpdateTraversal(
(*itr)->getNumChildrenRequiringUpdateTraversal()+delta );
}
}
}
// set the app callback itself.
_updateCallback = nc;
}从红色代码处可以看出,当节点已关联回调函数,再次设置新的回调函数时,不会影响父节点的遍历控制计数。
b)新节点设置回调函数再加入到场景图中void Node::setUpdateCallback(Callback* nc)
void Node::setUpdateCallback(Callback* nc);
void Node::setEventCallback(Callback* nc);
void Node::setCullingActive(bool active);
下面我们看,新节点先加入到场景图中再设置回调函数 与 新节点设置回调函数再加入到场景图中 控制计数的改变有何不同:
a) 新节点先加入到场景图中再设置回调函数
新节点添加前没有设置回调函数:
bool Group::addChild( Node *child ) { return Group::insertChild( _children.size(), child ); } bool Group::insertChild( unsigned int index, Node *child ) { if (!child) return false; #if ENSURE_CHILD_IS_UNIQUE if (containsNode(child)) { OSG_WARN<<"Adding non unique child to osg::Group, ignoring call"<<std::endl; return false; } #endif if (child) { // handle deprecated geometry configurations by calling fixDeprecatedData(). osg::Geometry* geometry = child->asGeometry(); if (geometry && geometry->containsDeprecatedData()) geometry->fixDeprecatedData(); // note ref_ptr<> automatically handles incrementing child's reference count. if (index >= _children.size()) { index = _children.size(); // set correct index value to be passed to the "childInserted" method _children.push_back(child); } else { _children.insert(_children.begin()+index, child); } // register as parent of child. child->addParent(this); // tell any subclasses that a child has been inserted so that they can update themselves. childInserted(index); dirtyBound(); // could now require app traversal thanks to the new subgraph, // so need to check and update if required. if (child->getNumChildrenRequiringUpdateTraversal()>0 || child->getUpdateCallback()) { setNumChildrenRequiringUpdateTraversal( getNumChildrenRequiringUpdateTraversal()+1 ); } // could now require app traversal thanks to the new subgraph, // so need to check and update if required. if (child->getNumChildrenRequiringEventTraversal()>0 || child->getEventCallback()) { setNumChildrenRequiringEventTraversal( getNumChildrenRequiringEventTraversal()+1 ); } // could now require disabling of culling thanks to the new subgraph, // so need to check and update if required. if (child->getNumChildrenWithCullingDisabled()>0 || !child->getCullingActive()) { setNumChildrenWithCullingDisabled( getNumChildrenWithCullingDisabled()+1 ); } if (child->getNumChildrenWithOccluderNodes()>0 || dynamic_cast<osg::OccluderNode*>(child)) { setNumChildrenWithOccluderNodes( getNumChildrenWithOccluderNodes()+1 ); } return true; } else return false; }从以上代码可以看出由于关联的回调函数函数指针为空且子节点遍历控制计数为零不会改变子节点所有相关的父节点的遍历计数。这段代码也提醒我们在子节点关联回调函数或遍历控制计数不为零的情况下都会改变父节点遍历控制计数(看红色代码部分)。
然后设置回调函数:void Node::setUpdateCallback(Callback* nc)
{
// if no changes just return.
if (_updateCallback==nc) return;
// updated callback has been changed, will need to update
// both _updateCallback and possibly the numChildrenRequiringAppTraversal
// if the number of callbacks changes.
// update the parents numChildrenRequiringAppTraversal
// note, if _numChildrenRequiringUpdateTraversal!=0 then the
// parents won't be affected by any app callback change,
// so no need to inform them.
if (_numChildrenRequiringUpdateTraversal==0 && !_parents.empty())
{
int delta = 0;
if (_updateCallback.valid()) --delta;
if (nc) ++delta;
if (delta!=0)
{
// the number of callbacks has changed, need to pass this
// on to parents so they know whether app traversal is
// required on this subgraph.
for(ParentList::iterator itr =_parents.begin();
itr != _parents.end();
++itr)
{
(*itr)->setNumChildrenRequiringUpdateTraversal(
(*itr)->getNumChildrenRequiringUpdateTraversal()+delta );
}
}
}
// set the app callback itself.
_updateCallback = nc;
}从红色代码处可以看出,当节点已关联回调函数,再次设置新的回调函数时,不会影响父节点的遍历控制计数。
b)新节点设置回调函数再加入到场景图中void Node::setUpdateCallback(Callback* nc)
bool Group::insertChild( unsigned int index, Node *child )从以上两个函数中可以看出,父节点遍历控制计数的改变是在加入到场景图中时自动处理的, 给节点设置回调函数或更改节点遍历控制计数都能将遍历下放到子节点,这两种方式有各自的用途,比如,我们需要在节点的virtual void traverse(osg::NodeVisitor& nv) 方法中处理所有的遍历情况,但该节点没有设置相关的回调函数或是子节点的访问是在过程中完成的,而不是串在场景图中,这里我们只需要将父节点遍历控制计数设置成大于0的数,节点遍历就会由根节点往下传递。
相关文章推荐
- Ext JS学习第十六天 事件机制event(一) DotNet进阶系列(持续更新) 第一节:.Net版基于WebSocket的聊天室样例 第十五节:深入理解async和await的作用及各种适用场景和用法 第十五节:深入理解async和await的作用及各种适用场景和用法 前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G
- Asp.net 2.0 自定义控件开发专题[详细探讨页面状态(视图状态和控件状态)机制及其使用场景](示例代码下载)
- osg lod pageLOD 区别+模型节点状态比较
- OSG更新遍历(updateTraversal)流程
- mysql 内部通过事件和游标自动更新表(状态值)
- Asp.net 2.0 自定义控件开发专题[详细探讨页面状态(视图状态和控件状态)机制及其使用场景](示例代码下载)
- OSG 事件处理机制 类图
- Http Status 304响应状态的资源更新机制
- vue nextTick深入理解---vue性能优化、DOM更新时机、事件循环机制
- Asp.net 2.0 自定义控件开发专题[详细探讨页面状态(视图状态和控件状态)机制及其使用场景](示例代码下载)
- Asp.net 2.0 自定义控件开发专题[详细探讨页面状态(视图状态和控件状态)机制及其使用场景](示例代码下载)
- Asp.net 2.0 自定义控件开发专题[详细探讨页面状态(视图状态和控件状态)机制及其使用场景](示例代码下载)
- datagrid combobox事件更新编辑状态下的datagrid行
- OSG节点访问、更新和回调
- Asp.net 2.0 自定义控件开发专题[详细探讨页面状态(视图状态和控件状态)机制及其使用场景](示例代码下载)
- Asp.net 2.0 自定义控件开发专题[详细探讨页面状态(视图状态和控件状态)机制及其使用场景](示例代码下载)
- easyui tree文本单击事件切换展开/折叠节点的状态
- 场景数据的动态更新setDataVariance(osg::Object::DYNAMIC) (转)
- Http Status 304响应状态的资源更新机制
- Asp.net 2.0 自定义控件开发专题[详细探讨页面状态(视图状态和控件状态)机制及其使用场景](示例代码下载)