带着上次的疑问我们继续探讨Away3D 的渲染流程。
在Away3D中所有的显示对象都是继承Object3D 的我们先看看显示对象和继承关系。
Object3D
|---ObjectContainer3D (3D显示容器)
|---Entity (所有的3D实体对象的抽象基类)
|---Mesh (网格对象)
|---Camera3D (摄影机[非显示对象])
|---SegmentSet (线段的集合可以绘制线)
|---Sprite3D (公告板始终面向摄像机)
以上显示对象中最常用的 是 Mesh 我们想看看Mesh 的结构。
Mesh 是由多个SubMesh 组成的,每个 SubMesh 可以拥有自己的 Geometry 和 Material。很多朋友说 Away3D 的mesh不支持多材质,其实是错误的。
你可以对 Mesh进行改造单独设置他的 SubMesh 即可。Geometry 和 Material这里占时不多说了大家自己用用就知道了。 每个Mesh都有一个MeshNode。
我们要寻找的答案也就在这里面。
我们搞清楚了显示对象下面就来了解下这些显示对象是如何被addChild 到舞台的。
ObjectContainer3D 类中实现了一个 addChild 的函数。在这个函数里大部分代码都是在做对象的管理,关键一步是 child.scene = _scene;
ObjectContainer3D 只是做了赋值处理并没有真正意义上的把对象添加到场景上。Entity类重写了scene的set 函数。
override public function set scene(value : Scene3D) : void
{
if (value == _scene)
return;
if (_scene)
_scene.unregisterEntity(this);
// callback to notify object has been spawned. Casts to please FDT
if (value)
value.registerEntity(this);
super.scene = value;
}
重写的scene set 函数 调用了 registerEntity 函数 把当前对象最为参数传递给了scene3d.由scene3d调用了添加到Partition3D中了。
但是添加到 Partition3D 中的时候并不是直接的添加当前对象 而是 添加了 当前对象的 node对象。至于为什么我们后面再说。
先回过头来看看之前收集器进过Partition3D 的 traverse函数。
if (_updatesMade)
updateEntities();
当有新的显示对象添加到了Partition3D中 Partition3D 将 _updatesMade自动设置为true了 这时候开始跟新显示对象以及该显示对象的子对象。
最后把所有要显示的对象的Node 都添加到了_rootNode中。然后开始 调用 acceptTraverser函数。前面说到了 Partition3D 中并不是直接的添加当前对象 而是 添加了 当前对象的 node对象。原因是Away3d 为了分离渲染和对象收集 把视锥剔除的逻辑在 node 中实现了。而对象本身是没有这个逻辑的。再进一步的debug 跟进发现进入了enterNode函数 开始计算视锥剔除。如果当前显示对象不在 视锥范围内 将不会被渲染。
下面再补充一下Away3D在渲染的过程中会先检查对象是否被 visible=false;如果是false 将不会被渲染。很多人在实际开发中把TextureMaterial 中的 alpha 设置等于0;但实际上这个显示对象还是会被渲染的。
Away3D 的实体收集器流程2