一,概述
Scene graph 的目的是组织物体。
两个原则: 1 。空间从属关系(树)
2 . Render State 的相似性。
原则一是为了快速剔除大批不可见物体。
原则二是为了减少 RenderState 的频繁改变。
二者均可使游戏速度大大提高。
原则一通过空间划分实现( bounding volumes ),原则通过排序实现。
然而两个原则是互不兼容的。若按 RS 排序,物体必然会分散于各个空间。理论上讲,两个原则那个更快就以那个为排序标准。
事实上 通常以原则一为准,即先将所有物体按空间从属关系分块,确定出可见物体后,再按 RS 排序。
以下为 scene graph 管理系统的宏观结构:
更新 Geometric State
(如顶点数据,变换,空间从属关系等)
更新 Render State
( global state , lights , effects 等)
剔除不可见物体
绘制(调用渲染系统)
用户作出反应
应用程序,回到初始循环。
在 WM4 中, culling pass 与 drawing pass 完全分开,便于多线程渲染。
二, scene graph 的几个核心类。
关系: Geometry 派生于 Spatial , Node 也派生于 Spatial 。 Spatial 基于 Object 。
Spatial 类中封转了 local transformation , world transformation 和 world bound 等等。
对以上三个名词的解释:
1. 世界空间中有一个房间,房间里有一个桌子。将桌子摆到房间里的变换为 local~
2 .将房间摆到世界空间中的变换为 world transformation 。同时,桌子也会进行 world transformation
3 每个物体都有自己的 local bound (基于物体坐标系),进行 world transformation 后, local bound 的位置,大小,形状都有可能变化,变化后成了 WORLD bound 。
Geometry 类中封装了所有的物体属性( position,index,color,texture coordinates,scale factor,local bounding volume,normals 等等)
除 local bound ,其余属性都被封装在 VertexBuffer 和 IndexBuffer 中。
另外,光照通过将 Light 类关联到 Geometry 实现(在 Geometry 类中存储一个 Light* ), local effect 通过将 ShaderEffect 类关联到 Geometry 实现。 Global effect 通过将 Effect 类关联到 Geometry 实现。
Node 类封装了对物体的组织函数,具体完成如下功能:
1. 在向下遍历中,先计算父节点的 world transformation ,再利用此 world~ 与子节点的 local transformation 相乘得到每个 child 的 worldtransformation 。
2. 向下遍历结束后,每个 geometry 会利用计算好的 world transformation 与 local bound 相乘得到 world bound 。
3. 向上遍历中,利用每一个 child 的 world bound 计算父节点的 world bound 。
注:
Node 的 world bound 乘以 world transformation 的逆变换可得 node 的 local bound ,但用处不大,所以未能支持,需要时实时计算即可。
Node 有 world bound ,但没有 model bound ,因为它只管理物体,本身并不是一个物体。
每个 Geometry 都有自己的 world transformation 和 world bound 。
三个核心类之间的关系:
Geometry 在 Spatial 的基础上增添了物体的所有属性和 local bound ,
Node 在 Spatial 的基础上增添了向子节点的链接以及对物体的管理方法。
如此一来, Geometry 只负责物体本身, Node 只负责对物体的管理,使两个截然不同的概念相互分开,方便了代码的维护与扩展。
注:一种更简洁的设计方法是只创建一个类 Node ,它既负责物体属性,又负责物体组织,这样做使场景图更加简洁,代码也更易于使用,但增加了代码维护和扩展的难度。
三,关于 sharing object 。
共享类的目的有二:
(1) 节省内存,避免了大量数据的复制。
(2) 节省美工工作量,避免特意制作世界中的每一个物体。(当然,不能有太强的重复感。)
但本 scene graph 并不支持 Node 类和 geometry 类的共享,即每一个节点只允许有一个父节点,但可以有多个子节点。因为如果支持多个父节点,代码开发难度会很大,详见 p230-232 。实际上,本 scenegraph 仍支持共享,不过是底层的共享,也就是说对 VB 和 IB 的共享。
四, Controller 类和 Modifiers 。
Controller 是一个抽象类,它的作用是实现动画;而 modifiers 是对一系列类的统称,它的作用是提供物体属性的附加信息,因此, modifier 通常由 Geometry 派生而来。
Controller 的分类:(详见 5,7 章)
(1) keyframe controller :用于关键帧动画。美工提供一系列关键帧(物体的位置和朝向) ,controller 对其进行平滑插值形成流畅的动画。
(2) inverse kinematic controller :用于自动动画,例如人物去拿杯子, controller 便会计算出相应的位置和朝向,控制人物的动画。
(3) vertex and normal controller :用于网格分解。
(4) Render state controller :用于某些特效,如动态纹理。
(5) Index controller :用于 LOD
基本思路是面向对象编程中的 open-close 原则。
Controller 是一个核心类,基于此派生新类以添加新的特性,但核心架构不发生变化这样易于维护和扩展。