Clayman's Graphics Corner

DirectX,Shader & Game Engine Programming

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Scene Management ---Node Update

作者:clayman

仅供个人学习使用,请勿转载,勿用于任何商业用途。 

 

         很多人都见过这张图吧,这是David Eberly介绍scene node updating时的插图,其中灰色表示发生过改变的节点。Eberly大师告诉我们,理想的更新方式,应该从a,b开始,但最关键的部分: 如何找到最靠近根节点的变化节点,却没有讨论。本文在这里尝试补上这一部分讨论,和以往的文章一样,只是讨论,并不一定能作为实际解决方案;)

 

         整个scene update的代价等于更新每个节点的代价加上遍历相关节点的代价。假设每个节点更新的代价已经固定,那么唯一能做的就是减少遍历次数,避免访问不必更新的节点。用以下公式表示整个更新代价:

cost = treeWalk + nodeUpdate + findingUpdateRoot;

 

显然,最差情况为:

cost = fullTreeWalk + nodeUpdate;

 

         因此,要保证treeWalk + findingUpdateRoot <= fullTreeWalk,否则所谓的优化就没意义了。这个不等式有可能成立吗?不一定,当大部分或者所有节点都需要更新时,treeWalk + findingUpdateRoot很可能大于fullTreeWalk。如果你的游戏属于这种情况,那么不用费力找潜在的a,b节点了,直接遍历整个树吧。另一方面,当仅有少部分节点需要更新时,寻找最靠近根节点的变化节点就很有意义了。我们把这种方法称为bucketed update,如其名称所示,发生改变的节点把自己放到bucket, 更新时,检查bucket中是否有节点,如果有则更新节点及其子节点。这里很重要的一个问题是,当a,b,c,d都在bucket中时,必须找出最靠近根的那个。最简单的方法: 不同高度的节点放到不同bucket中,从最底层bucket开始更新。你可能会说scene graph的树高为n的话,岂不是需要nbucket组? 确实如此,好在对一般游戏来说,scene graph的结构通常很平(flat),不会太深,有些引擎更是把高度n限制在一个非常小的值,比如3,因此这种方法在很大程度上还是相当可行。

//game logic
sceneNode.setXXX()
{
   ...........
   
if(!requireUpdate)
     requireUpdate
=true;
     AddToBucket(treeLevel,
this)
}

//updating phase
foreach bucket in bucketGroup
   
foreach node in bucket
      
if(node.requireUpdate)
         node.Update;

 

 

 

posted on 2010-05-27 14:39  clayman  阅读(1755)  评论(4编辑  收藏  举报