2018-09-01
场景管理是渲染引擎的核心功能,我们希望能够把所有的渲染物体合理的组织在一起,而且能够方便的查找、管理。本质上就是设计一个或者多个数据结构。这个目标很容易实现,放在一个数组里就可以了,各种操作的代价也不是很大。但是,这是不行的。
首先,我们需要把显示物体分组,一堆对象可能是属于一起的,在逻辑上在一个集合,虽然我们可以用额外的数据结构来进行分组管理,那很容出错。所以,我们这个数据结构具有递归保存自身节点类型的功能,其实就是一棵树了。
其次,有的节点是逻辑上的,它只是起保存分组信息的功能(Group),还需要让有些节点保存 渲染物体信息的功能(Geode)。那么,这就需要使用C++ 的继承机制,Geode继承于 Group,另外添加一些保存渲染信息的接口即可。有些引擎不是这么设计的,可参与渲染的节点只能是叶子节点。我倒是觉得OSG的设计更方便一些。目前,osg::Geode 默认它的children都是可绘制对象,因为有碰撞检测的需求,可绘制对象必然会碰撞,所以会强制转换为osg::Drawable类型,这样会导致一个问题:osg::Geode不能把组织节点作为 子节点。这个问题一般不大。
第三,当我们想要重用一个节点时该如何呢?总不能把节点的渲染数据复制一份吧。所以,需要场景管理的数据结构支持一个子节点有多个父节点。那么,这棵树现在已经变成一个有向无环图 (Directed Acyclic Graph)了。节点需要增加一个指向多个父节点指针的数组。
第四,OpenGL是状态机机制,但是,场景管理不需要管理渲染API 究竟是如何渲染的,它的职责只是管理了静态的组织结构。如,我们想给一组节点设置属性,如透明与否、缩放程度、是否隐藏、线条粗细、颜色等,所以,节点需要一个保存这些信息的对象(StateSet)。
第五,因为我们想要自动管理场景内存的功能,如删掉一个子节点,且没有其他对象再引用它,那么就可以把它析构掉,而且需要给子节点对象提供保存用户填入的任何类型信息功能,这就需要提供智能指针的支持,所以提供Object和Reference类支