文章目录
Cesium拾取源码分析
拾取大体上的思路是:在拾取的时候,将物体渲染到帧缓冲区,然后读取拾取的3x3区域像素值,再根据像素值去匹配拾取到的物体。在整个流程中,有两个重要的类:BatchTable和DerivedCommand,前者主要是负责准备渲染需要的纹理、变量,用于后续的查找,DerivedCommand则是负责创建渲染到帧缓冲区的绘制命令。分三个部分来展开说明:BatchTable的作用、DerivedCommand的作用、最后是拾取的流程。
1.BatchTable的作用
BatchTable在整个拾取的流程中扮演了一个非常重要的角色,所以在开始说明拾取流程之前,有必要先了解下,在几何转为DrawCommand的流程,BatchTable起到了什么样的作用。
1.1 BatchTable的创建
在Primitive的update方法中,会执行createBatchTable()从而创建BatchTable,然后会执行batchTable.setBatchedAttribute(i, attributeIndex, value)方法设置BatchTable中用到的属性值,这些属性值会以数组的形式存放在batchTable._batchValues中。
然后是context.createPickId(pickObject),其中会调用createPickId创建PickId对象,PickId对象有:key、color、以及几何本身(Primitive),在创建的时候,此PickId对象会添加到context的_pickObjects字典,用于后面的查找。color的值同样写入batchTable._batchValues中。
Context.prototype.createPickId = function (object) {
//>>includeStart('debug', pragmas.debug);
Check.defined("object", object);
//>>includeEnd('debug');
// the increment and assignment have to be separate statements to
// actually detect overflow in the Uint32 value
++this._nextPickColor[0];
const key = this._nextPickColor[0];
if (key === 0) {
// In case of overflow
throw new RuntimeError("Out of unique Pick IDs.");
}
this._pickObjects[key] = object;
return new PickId(this._pickObjects, key, Color.fromRgba(key));
};
1.2 BatchTable的更新
这里主要是创建BatchTable的纹理,纹理的值来自前面提到的batchTable._batchValues,纹理宽度根据属性值多少来定,高度都是1。
BatchTable.prototype.update = function (frameState) {
if (
(defined(this._texture) && !this._batchValuesDirty) ||
this._attributes.