Away3D 的实体收集器流程1

View3D 顾名思义 它就是一个3D视口,视口的默认值是无穷大的,即相当于“窗口”是无限大的,我们看到的将是外面的所有景物
即flash尺寸是视口的有效视域.传统电视的高宽比为4:3,现在的高清电视的高宽比为16:9,你也可以如此这般地去设置。
它是一个Sprite 的子类。主要用于创建 3D场景 相机 及渲染。相信很多人都和我一样在想
View3D 它究竟做了什么?很多人估计想都不用想可以回答这个问题 “渲染”!那么它是如何渲染的?除了渲染它还干了什么?
带着这些问题打开 Away3d 源码 View3D.as 寻找真相。
源码打开乍眼一看几百行代码晕了。无从下手!学java 和C 的程序员都知道要运行程序先得找到main函数。同样先找找主入口吧,既然都知道它是做渲染的先看看render()函数。
下面从render()函数下手逐步分析。
以下是render()函数源码:

public function render() : void
{
     //if context3D has Disposed by the OS,don‘t render at this frame
     if (!stage3DProxy.recoverFromDisposal())

   {
        _backBufferInvalid = true;
        return;
     }
   
     // reset or update render settings
     if (_backBufferInvalid)
        updateBackBuffer();
   
     if (_shareContext && _layeredView)
        stage3DProxy.clearDepthBuffer();

  if (!_parentIsStage)

   {
        var globalPos : Point = parent.localToGlobal(_localPos);
        if (_globalPos.x != globalPos.x || _globalPos.y != globalPos.y)

      {
           _globalPos = globalPos;
           _globalPosDirty = true;
        }
     }
   
     if (_globalPosDirty)
        updateGlobalPos();

    updateTime(); //更新本地运行时间

  updateViewSizeData();

   _entityCollector.clear();

   // collect stuff to render 收集的东西呈现
     _scene.traversePartitions(_entityCollector);

  // update picking
     _mouse3DManager.updateCollider(this);

  if (_requireDepthRender)
        renderSceneDepthToTexture(_entityCollector);

  // todo: perform depth prepass after light update and before final render
     if (_depthPrepass)
        renderDepthPrepass(_entityCollector);

  _renderer.clearOnRender = !_depthPrepass;

  if (_filter3DRenderer && _stage3DProxy._context3D)

   {
        _renderer.render(_entityCollector, _filter3DRenderer.getMainInputTexture(_stage3DProxy), _rttBufferManager.renderToTextureRect);
        _filter3DRenderer.render(_stage3DProxy, camera, _depthRender);
     }

   else

   {
        _renderer.shareContext = _shareContext;
       if (_shareContext)

      {
           _renderer.render(_entityCollector, null, _scissorRect);
        }

      else

     {
           _renderer.render(_entityCollector);
       }

  }
   
     if (!_shareContext) {
        stage3DProxy.present();

  // fire collected mouse events
      _mouse3DManager.fireMouseEvents();
     }

   // clean up data for this render
     _entityCollector.cleanUp();
   
     // register that a view has been rendered
     stage3DProxy.bufferClear = false;
  }

分析:
if (!stage3DProxy.recoverFromDisposal())
{
  _backBufferInvalid = true;
  return;
}
stage3DProxy 是Away3D提供一个代理类来管理一个Stage3D实例,对Context3D的常用操作进行了封装。
recoverFromDisposal() 函数对显卡驱动程序的类型进行了检测。
这个判断意思就是如果你的显卡驱动不是context3D支持的就不在此帧渲染了.

if (_backBufferInvalid)
    updateBackBuffer();
    
updateBackBuffer函数用于更新后台缓存区。

if (!_parentIsStage)
    updateGlobalPos();

如果当前的View3D所在的父容器不是Stage上那么Away就会调用updateGlobalPos()函数来更新获取全局坐标。

updateTime();函数是用来统计上一帧所渲染的时间。

好了其他的就不多废话了大家有兴趣可以去看看源码,下面重点介绍Away3D的一项重要功能实体收集器。

在updateTime函数下方有一段代码 _entityCollector.clear();表示每次在渲染的前期会清空实体收集器,然后再进行新的一轮收集。

_scene.traversePartitions(_entityCollector);

scene 表示是当前渲染的场景。下面就跟着traversePartitions 函数一步步去跟进看看他是如何收集的。

每一个 Scene3D 在初始化的时候都会创建一个_partitions:Vector.<Partition3D>。Partition3D是一个空间的分区系统的核心。

它用于将三维场景分级成多个互不重叠的子空间,从而形成一个树型数据结构。

在Scene3D类中的 traversePartitions 函数可以看见 每次在收集的时候 都会循环_partitions 然后 调用了 Partition3D 类的

traverse 函数进行收集。到目前为止我们视乎还是没有搞清楚entityCollector到底是如何收集的。细心的朋友可能已经发现了

traverse 函数里的 _rootNode.acceptTraverser(traverser); 这段代码。那这个_rootNode 到底是啥呢?下一节我再深入的探讨。

Away3D 的实体收集器流程1

时间: 2024-12-10 12:57:38

Away3D 的实体收集器流程1的相关文章

Away3D 的实体收集器流程2

带着上次的疑问我们继续探讨Away3D 的渲染流程. 在Away3D中所有的显示对象都是继承Object3D 的我们先看看显示对象和继承关系. Object3D |---ObjectContainer3D  (3D显示容器) |---Entity (所有的3D实体对象的抽象基类) |---Mesh (网格对象) |---Camera3D (摄影机[非显示对象]) |---SegmentSet (线段的集合可以绘制线) |---Sprite3D (公告板始终面向摄像机) 以上显示对象中最常用的 是

Away3D 的实体收集器Bug

最近在改Away3D源码的时候遇到个很郁闷的问题,发现创建的Mesh 释放不掉. 分析源码发现 EntityListItemPool 类中逻辑Bug在getItem()函数中发现_poolSize 对象池大小如果够用的情况下 它采用的方式是复用EntityListItem 那么假设我删除了场景上有10个对象我全部删除了然后我再创建9个 这时候总有1个对象是被缓存着的.一直要等到我创建第10个对象他才会被释放掉. 没辙了跑到 看看对象销毁流程吧. 对象被销毁时会调用 Scene3D 的 unreg

【5】JVM-垃圾收集器

通过学习了解到现在商用的JVM中的垃圾收集采用的是分代收集算法,即针对不同年代采用不同的收集算法.在JVM中,GC主要作用于堆内存中,堆内存又被划分为新生代和老年代,由于新生代对象绝大多数是朝生夕死,而老年代相对存活时间就很长,故而需要使用不同的垃圾收集机制,所以垃圾收集器也就分为新生代收集器和老年代收集器,两者相互组合进行JVM堆内存的空间回收(下图中相连的垃圾收集器表示可以相互组合,注意Serial Old和CMS也可以联合进行老年代的垃圾收集).JDK6u14中开始测试的G1垃圾收集器,正

万能日志数据收集器 Fluentd - 每天5分钟玩转 Docker 容器技术(91)

前面的 ELK 中我们是用 Filebeat 收集 Docker 容器的日志,利用的是 Docker 默认的 logging driver json-file,本节我们将使用 fluentd 来收集容器的日志. Fluentd 是一个开源的数据收集器,它目前有超过 500 种的 plugin,可以连接各种数据源和数据输出组件.在接下来的实践中,Fluentd 会负责收集容器日志,然后发送给 Elasticsearch.日志处理流程如下: 这里我们用 Filebeat 将 Fluentd 收集到的

2020了你还不会Java8新特性?(五)收集器比较器用法详解及源码剖析

收集器用法详解与多级分组和分区 为什么在collectors类中定义一个静态内部类? static class CollectorImpl<T, A, R> implements Collector<T, A, R> 设计上,本身就是一个辅助类,是一个工厂.作用是给开发者提供常见的收集器实现.提供的方法都是静态方法,可以直接调用. 函数式编程最大的特点:表示做什么,而不是如何做.开发者更注重如做什么,底层实现如何做. /** * Implementations of {@link

ThreadLocal 作为数据收集器使用

接到一个很特殊的需求: 系统用户存在两种类型,一种是普通的,另外一种称之为admin,admin用户很特殊.对于普通用户,当系统修改他自身属性(包含很多属性,比如:性别.绑定的信用卡.身份证.出生日期等)系统不仅要保存用户信息,而且还需要保存数据的变化(这称之为audit log,比如用户修改了出生日期,那么audit log需要保存之前的出生日期以及修改后的出生日期). 对admin用户的操作与普通用户不一样,当系统检测到产生audit log之后,需要暂停当前流程弹出一个对话框提示用户,选中

JAVA G1收集器 第11节

JAVA G1收集器 第11节 上两章我们讲了新生代和年老代的收集器,那么这一章的话我们就要讲一个收集范围涵盖整个堆的收集器——G1收集器. 先讲讲G1收集器的特点,他也是个多线程的收集器,能够充分利用多个CPU进行工作,收集方式也与CMS收集器类似,因此不会有太久的停顿. 虽然回收的范围是整个堆,但还是有分代回收的回收方式.在年轻代依然采用复制算法:年老代也同样采用“标记-清除-整理”算法.但是,新生代与老年代在堆内存中的布局就和以往的收集器有着很大的区别:G1将整个堆分成了一个个大小相等的独

深入JVM系列(二)之GC机制、收集器与GC调优(转)

一.回顾JVM内存分配 需要了解更多内存模式与内存分配的,请看 深入JVM系列(一)之内存模型与内存分配 1.1.内存分配: 1.对象优先在EDEN分配2.大对象直接进入老年代 3.长期存活的对象将进入老年代 4.适龄对象也可能进入老年代:动态对象年龄判断 动态对象年龄判断: 虚拟机并不总是要求对象的年龄必须达到MaxTenuringThreshold才能晋升到老年代,当Survivor空间的相同年龄的所有对象大小总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代

JVM-垃圾收集器

本篇主要介绍一下JVM的几种垃圾收集器.其示意图如下所示,上面的三个是新生代的收集器,下面三个是老年代的收集器,其中G1收集器是可以用于新生代和老年代的收集工作. JVM垃圾收集器 1.Serial(串行收集器):用于新生代GC,复制算法,启动时默认为Client模式,GC的线程为单线程.缺点是因为单线程GC,会造成中断的时间(Sop-the-world)比较大.(对于单核的CPU来说,比并行收集的效率要高)其示意图如下所示: Serial串行收集器 2.ParNew(并行收集器):与Seria