@mesh3d/cesium-vectortile-gl 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +120 -0
- package/Source/Cesium.d.ts +2692 -0
- package/Source/VectorTileLOD.js +494 -0
- package/Source/VectorTileRenderList.js +65 -0
- package/Source/VectorTileset.js +309 -0
- package/Source/layers/BackgroundRenderLayer.js +82 -0
- package/Source/layers/FillRenderLayer.js +18 -0
- package/Source/layers/IRenderLayer.js +128 -0
- package/Source/layers/LineRenderLayer.js +94 -0
- package/Source/layers/SymbolRenderLayer.js +31 -0
- package/Source/layers/index.js +16 -0
- package/Source/layers/registerRenderLayer.js +24 -0
- package/Source/layers/visualizers/FillLayerVisualizer.js +420 -0
- package/Source/layers/visualizers/ILayerVisualizer.js +73 -0
- package/Source/layers/visualizers/LineLayerVisualizer.js +565 -0
- package/Source/layers/visualizers/SymbolLayerVisualizer.js +179 -0
- package/Source/sources/GeoJSONSource.js +46 -0
- package/Source/sources/ISource.js +39 -0
- package/Source/sources/VectorSource.js +45 -0
- package/Source/sources/granularitySettings.js +20 -0
- package/Source/sources/index.js +11 -0
- package/Source/sources/registerSource.js +19 -0
- package/Source/style/StyleLayer.js +43 -0
- package/Source/style/StyleLayerProperties.js +43 -0
- package/Source/style/index.js +2 -0
- package/dist/cvt-gl.js +10642 -0
- package/dist/cvt-gl.js.map +1 -0
- package/dist/cvt-gl.min.js +135 -0
- package/dist/cvt-gl.min.js.map +1 -0
- package/index.js +6 -0
- package/logo.svg +47 -0
- package/package.json +36 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ILayerVisualizer } from "./visualizers/ILayerVisualizer"
|
|
2
|
+
import { IRenderLayer } from "./IRenderLayer"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @type {Record<string,typeof IRenderLayer>}
|
|
6
|
+
*/
|
|
7
|
+
const RenderLayers = {}
|
|
8
|
+
/**
|
|
9
|
+
* @type {Record<string,typeof ILayerVisualizer>}
|
|
10
|
+
*/
|
|
11
|
+
const LayerVisualizers = {}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 注册图层类型,设置渲染图层类和图层渲染器类(非必须)
|
|
15
|
+
* @param {"symbol" | "fill" | "line" | "circle" | "heatmap" | "fill-extrusion" | "raster" | "hillshade" | "color-relief" | "background"} type 图层类型
|
|
16
|
+
* @param {typeof IRenderLayer} renderLayerCls 渲染图层类,必须继承 IRenderLayer
|
|
17
|
+
* @param {typeof ILayerVisualizer} [layerVisualizerCls] 图层渲染器类,必须继承 ILayerVisualizer
|
|
18
|
+
*/
|
|
19
|
+
function registerRenderLayer(type, renderLayerCls, layerVisualizerCls) {
|
|
20
|
+
RenderLayers[type] = renderLayerCls
|
|
21
|
+
LayerVisualizers[type] = layerVisualizerCls
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { RenderLayers, LayerVisualizers, registerRenderLayer }
|
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
import { VectorTileFeature, classifyRings } from "@mapbox/vector-tile"
|
|
2
|
+
import { IRenderLayer } from "../IRenderLayer"
|
|
3
|
+
import { ILayerVisualizer } from "./ILayerVisualizer"
|
|
4
|
+
import { loadGeometry } from "maplibre-gl/src/data/load_geometry"
|
|
5
|
+
import { EXTENT } from 'maplibre-gl/src/data/extent';
|
|
6
|
+
import { subdividePolygon } from "maplibre-gl/src/render/subdivision"
|
|
7
|
+
import { granularitySettings } from "../../sources/granularitySettings";
|
|
8
|
+
import { warnOnce } from "maplibre-gl/src/util/util";
|
|
9
|
+
import { VectorTileset } from "../../VectorTileset";
|
|
10
|
+
|
|
11
|
+
export class FillFeature {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.featureId = 0
|
|
14
|
+
this.fillColor = Cesium.Color.BLACK.clone()
|
|
15
|
+
this.fillOpacity = 1
|
|
16
|
+
this.coordinates = []
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class FillLayerVisualizer extends ILayerVisualizer {
|
|
21
|
+
constructor(layers, tile) {
|
|
22
|
+
super(layers, tile)
|
|
23
|
+
|
|
24
|
+
this.geometryInstances = []
|
|
25
|
+
this.primitive = null
|
|
26
|
+
this.commandsReady = false
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {VectorTileFeature[]} features
|
|
31
|
+
* @param {IRenderLayer} layer
|
|
32
|
+
* @param {Cesium.frameState} frameState
|
|
33
|
+
* @param {VectorTileset} tileset
|
|
34
|
+
*/
|
|
35
|
+
addLayer(features, layer, frameState, tileset) {
|
|
36
|
+
const style = layer.style
|
|
37
|
+
const { tile, geometryInstances } = this
|
|
38
|
+
const granularity = granularitySettings.globe.line.getGranularityForZoomLevel(tile.z) / 2
|
|
39
|
+
const scope = this
|
|
40
|
+
let featureId = 0
|
|
41
|
+
const promoteId = tileset.sources[layer.style.source].styleSource.promoteId
|
|
42
|
+
|
|
43
|
+
for (const sourceFeature of features) {
|
|
44
|
+
const featureType = VectorTileFeature.types[sourceFeature.type]
|
|
45
|
+
const properties = sourceFeature.properties
|
|
46
|
+
if (featureType !== 'Polygon') continue
|
|
47
|
+
|
|
48
|
+
const fillPattern = style.paint.getDataValue('fill-pattern', tile.z, sourceFeature)
|
|
49
|
+
if (fillPattern) {
|
|
50
|
+
warnOnce('fill图层:不支持纹理填充(fill-pattern)')
|
|
51
|
+
continue
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const sourceFeatureId = sourceFeature.id || properties[promoteId]
|
|
55
|
+
//读取图层样式属性
|
|
56
|
+
const fillColor = style.convertColor(style.paint.getDataValue('fill-color', tile.z, sourceFeature))
|
|
57
|
+
const fillOpacity = style.paint.getDataValue('fill-opacity', tile.z, sourceFeature)
|
|
58
|
+
|
|
59
|
+
//关键:对投影坐标细分,而不是使用cesium内置的细分
|
|
60
|
+
const vtCoords = loadGeometry(sourceFeature)
|
|
61
|
+
const polygons = classifyRings(vtCoords)
|
|
62
|
+
for (const coordinates of polygons) {
|
|
63
|
+
if (coordinates.some(ring => ring.length < 3)) continue
|
|
64
|
+
|
|
65
|
+
const batchId = geometryInstances.length
|
|
66
|
+
if (featureId == 0) {
|
|
67
|
+
layer.firstBatchId = batchId
|
|
68
|
+
}
|
|
69
|
+
layer.lastBatchId = batchId
|
|
70
|
+
|
|
71
|
+
const fillFeature = {
|
|
72
|
+
coordinates,
|
|
73
|
+
featureId,
|
|
74
|
+
fillColor,
|
|
75
|
+
fillOpacity,
|
|
76
|
+
properties,
|
|
77
|
+
//保存原始数据的要素id,后续可以用来支持 featureState 表达式,这个表达式可以实现选定要素高亮显示
|
|
78
|
+
id: sourceFeatureId,
|
|
79
|
+
//保存batchId,将矢量要素与几何顶点关联,后续可以实时更新图层样式
|
|
80
|
+
batchId
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
scope.addFeature(fillFeature, granularity)
|
|
84
|
+
|
|
85
|
+
featureId++
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
layer.offsets = []
|
|
90
|
+
layer.counts = []
|
|
91
|
+
|
|
92
|
+
this.layers.push(layer)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 创建一个多边形的几何体实例
|
|
97
|
+
* @param {FillFeature} feature
|
|
98
|
+
* @param {number} granularity
|
|
99
|
+
*/
|
|
100
|
+
addFeature(feature, granularity) {
|
|
101
|
+
const geometryInstances = this.geometryInstances
|
|
102
|
+
const { coordinates, fillColor, fillOpacity } = feature
|
|
103
|
+
const colorBytes = fillColor.toBytes()
|
|
104
|
+
colorBytes[3] = Math.floor(colorBytes[3] * fillOpacity)
|
|
105
|
+
|
|
106
|
+
// 使用 maplibre-gl 的 subdividePolygon 基于投影坐标进行细分,
|
|
107
|
+
// 而不是在转成世界坐标后再使用 Cesium.PolygonGeometry 构建,这样才能避免出现自相交、破面等现象。
|
|
108
|
+
// 商业版性能优化:将此过程移到 Web Worker ,多线程加速,同时避免主线程阻塞
|
|
109
|
+
|
|
110
|
+
const subdivisionRes = subdividePolygon(coordinates, this.tile, granularity, false)
|
|
111
|
+
const verticesFlattened = subdivisionRes.verticesFlattened
|
|
112
|
+
const coordDeg = [0, 0], cartesian = new Cesium.Cartesian3()
|
|
113
|
+
const vertCount = verticesFlattened.length / 2
|
|
114
|
+
const positions = new Float64Array(vertCount * 3)
|
|
115
|
+
const normals = new Float32Array(vertCount * 3)
|
|
116
|
+
const sts = new Float32Array(vertCount * 2)
|
|
117
|
+
|
|
118
|
+
for (let i = 0, j = 0; i < verticesFlattened.length; i += 2, j++) {
|
|
119
|
+
const x = verticesFlattened[i], y = verticesFlattened[i + 1]
|
|
120
|
+
const coord = this.tile.transformPoint(x, y, coordDeg)
|
|
121
|
+
const position = Cesium.Cartesian3.fromDegrees(coord[0], coord[1], 0, null, cartesian)
|
|
122
|
+
positions[j * 3] = position.x
|
|
123
|
+
positions[j * 3 + 1] = position.y
|
|
124
|
+
positions[j * 3 + 2] = position.z
|
|
125
|
+
|
|
126
|
+
const normal = Cesium.Cartesian3.normalize(position, position)
|
|
127
|
+
normals[j * 3] = normal.x
|
|
128
|
+
normals[j * 3 + 1] = normal.y
|
|
129
|
+
normals[j * 3 + 2] = normal.z
|
|
130
|
+
|
|
131
|
+
sts[j * 2] = x / EXTENT
|
|
132
|
+
sts[j * 2 + 1] = y / EXTENT
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const indices = new (vertCount > 65535 ? Uint32Array : vertCount > 255 ? Uint16Array : Uint8Array)(subdivisionRes.indicesTriangles)
|
|
136
|
+
|
|
137
|
+
const geometry = new Cesium.Geometry({
|
|
138
|
+
attributes: {
|
|
139
|
+
position: {
|
|
140
|
+
componentDatatype: Cesium.ComponentDatatype.DOUBLE,
|
|
141
|
+
componentsPerAttribute: 3,
|
|
142
|
+
normalize: false,
|
|
143
|
+
values: positions
|
|
144
|
+
},
|
|
145
|
+
normal: {
|
|
146
|
+
componentDatatype: Cesium.ComponentDatatype.FLOAT,
|
|
147
|
+
componentsPerAttribute: 3,
|
|
148
|
+
normalize: false,
|
|
149
|
+
values: normals
|
|
150
|
+
},
|
|
151
|
+
st: {
|
|
152
|
+
componentDatatype: Cesium.ComponentDatatype.FLOAT,
|
|
153
|
+
componentsPerAttribute: 2,
|
|
154
|
+
normalize: false,
|
|
155
|
+
values: sts
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
primitiveType: Cesium.PrimitiveType.TRIANGLES,
|
|
159
|
+
indices: indices,
|
|
160
|
+
boundingSphere: Cesium.BoundingSphere.fromVertices(positions)
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
const cartographic = Cesium.Cartographic.fromCartesian(geometry.boundingSphere.center)
|
|
164
|
+
cartographic.height = 0//包围盒中心可能高于或者低于地面,需要避免双击锁定视角时进入地下
|
|
165
|
+
const center = Cesium.Cartographic.toCartesian(cartographic, null, cartesian)
|
|
166
|
+
|
|
167
|
+
const instance = new Cesium.GeometryInstance({
|
|
168
|
+
geometry,
|
|
169
|
+
attributes: {
|
|
170
|
+
color: new Cesium.GeometryInstanceAttribute({
|
|
171
|
+
componentDatatype: Cesium.ComponentDatatype.UNSIGNED_BYTE,
|
|
172
|
+
componentsPerAttribute: 4,
|
|
173
|
+
normalize: true,
|
|
174
|
+
value: colorBytes
|
|
175
|
+
}),
|
|
176
|
+
},
|
|
177
|
+
//通过entity的形式暴露给Cesium pickEntity,这样点击时系统自带的inforbox可以弹出
|
|
178
|
+
id: new Cesium.Entity({
|
|
179
|
+
position: center,
|
|
180
|
+
id: feature.id,
|
|
181
|
+
properties: feature.properties
|
|
182
|
+
})
|
|
183
|
+
})
|
|
184
|
+
geometryInstances.push(instance)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
createPrimitive() {
|
|
188
|
+
const primitive = new Cesium.Primitive({
|
|
189
|
+
geometryInstances: this.geometryInstances,
|
|
190
|
+
asynchronous: !(this.geometryInstances[0].geometry instanceof Cesium.Geometry),
|
|
191
|
+
appearance: new Cesium.PerInstanceColorAppearance({
|
|
192
|
+
flat: true,
|
|
193
|
+
translucent: false,
|
|
194
|
+
renderState: {
|
|
195
|
+
//这里设置是没有用的,只要 translucent 为 false,
|
|
196
|
+
//Cesium 内部都会覆盖成 true,所以我们需要在 DrawCommand 创建完成后再设置
|
|
197
|
+
depthMask: false,
|
|
198
|
+
},
|
|
199
|
+
fragmentShaderSource:/*glsl*/`
|
|
200
|
+
in vec4 v_color;
|
|
201
|
+
|
|
202
|
+
uniform vec4 tileId;
|
|
203
|
+
uniform sampler2D tileIdTexture;
|
|
204
|
+
|
|
205
|
+
void main()
|
|
206
|
+
{
|
|
207
|
+
vec2 id_st = gl_FragCoord.xy / czm_viewport.zw;
|
|
208
|
+
vec4 bgId = texture(tileIdTexture, id_st);
|
|
209
|
+
if (!all(equal(bgId, tileId)))
|
|
210
|
+
{
|
|
211
|
+
discard;
|
|
212
|
+
}
|
|
213
|
+
out_FragColor = v_color;
|
|
214
|
+
}
|
|
215
|
+
`
|
|
216
|
+
}),
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
//通过定义 Primitive 私有变量 _geometries、_batchTable 的 setter 和 getter,
|
|
220
|
+
//监听合批几何体和批次表的创建:
|
|
221
|
+
//1、几何体创建完成后,根据 batchId 和 featureId,计算每个图层几何体的起始索引(offset)和索引数量(count)
|
|
222
|
+
//2、批次表创建完成后,保存备用
|
|
223
|
+
let scope = this
|
|
224
|
+
Object.defineProperties(primitive, {
|
|
225
|
+
_geometries: {
|
|
226
|
+
get() {
|
|
227
|
+
return this._geometries_
|
|
228
|
+
},
|
|
229
|
+
set(geometries) {
|
|
230
|
+
this._geometries_ = geometries
|
|
231
|
+
if (geometries) {
|
|
232
|
+
scope.onGeometriesLoaded(geometries)
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
scope = null
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
_batchTable: {
|
|
240
|
+
get() {
|
|
241
|
+
return this._batchTable_
|
|
242
|
+
},
|
|
243
|
+
set(batchTable) {
|
|
244
|
+
this._batchTable_ = batchTable
|
|
245
|
+
if (batchTable) {
|
|
246
|
+
scope.onBatchTableCreated(batchTable)
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
this.primitive = primitive
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* 根据 batchId 和 featureId,计算每个图层几何体的起始索引(offset)和索引数量(count)
|
|
257
|
+
* @param {Cesium.Geometry[]} geometries
|
|
258
|
+
*/
|
|
259
|
+
onGeometriesLoaded(geometries) {
|
|
260
|
+
//Cesium 几何体合批结果可能是多个几何体,对应多个 DrawCommand
|
|
261
|
+
for (let pass = 0; pass < geometries.length; pass++) {
|
|
262
|
+
const batches = {}
|
|
263
|
+
const geometry = geometries[pass];
|
|
264
|
+
const batchIds = geometry.attributes.batchId.values
|
|
265
|
+
const indices = geometry.indices
|
|
266
|
+
|
|
267
|
+
//提取每个批次的起始和结束索引
|
|
268
|
+
let currBatchId = -1
|
|
269
|
+
let currBatch = null
|
|
270
|
+
for (let i = 0; i < indices.length; i++) {
|
|
271
|
+
const vertIndex = indices[i]
|
|
272
|
+
const batchId = batchIds[vertIndex]
|
|
273
|
+
if (currBatchId !== batchId) {
|
|
274
|
+
currBatchId = batchId
|
|
275
|
+
currBatch = batches[currBatchId] = {
|
|
276
|
+
begin: i,
|
|
277
|
+
end: i
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
currBatch.end = i
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
//根据图层批次范围,提取图层几何体索引范围,即起始索引(offset)和索引数量(count)
|
|
284
|
+
for (const layer of this.layers) {
|
|
285
|
+
const { firstBatchId, lastBatchId } = layer
|
|
286
|
+
if (firstBatchId === -1 || lastBatchId === -1) {
|
|
287
|
+
continue
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
let begin = -1, end = -1
|
|
291
|
+
for (let batchId = firstBatchId; batchId <= lastBatchId; batchId++) {
|
|
292
|
+
const batch = batches[batchId]
|
|
293
|
+
if (batch) {
|
|
294
|
+
if (begin === -1) begin = batch.begin
|
|
295
|
+
end = batch.end
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (begin === -1 || end === -1) {
|
|
300
|
+
continue
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
//起始和结束索引,索引数量需要加1
|
|
304
|
+
layer.offsets[pass] = begin
|
|
305
|
+
layer.counts[pass] = end - begin + 1
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* 保存 Cesium Primitive 创建的批次表。图层样式变化时,通过更新批次表传递到GPU,同步更新渲染效果
|
|
312
|
+
* @param {Cesium.BatchTable} batchTable
|
|
313
|
+
*/
|
|
314
|
+
onBatchTableCreated(batchTable) {
|
|
315
|
+
this._batchTable = batchTable
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* 使用合批后的 drawCommand 创建副本,为渲染图层分配 drawCommand
|
|
320
|
+
* @param {Cesium.DrawCommand[]} batchedCommandList
|
|
321
|
+
* @param {VectorTileset} tileset
|
|
322
|
+
*/
|
|
323
|
+
createLayerCommands(batchedCommandList, tileset) {
|
|
324
|
+
const renderState = Cesium.RenderState.fromCache({
|
|
325
|
+
id: 'fill',
|
|
326
|
+
blending: Cesium.BlendingState.ALPHA_BLEND,
|
|
327
|
+
depthMask: false,
|
|
328
|
+
depthTest: {
|
|
329
|
+
enabled: true
|
|
330
|
+
},
|
|
331
|
+
cull: {
|
|
332
|
+
enabled: true
|
|
333
|
+
}
|
|
334
|
+
})
|
|
335
|
+
const tileId = this.tile.tileId
|
|
336
|
+
this.renderState = renderState
|
|
337
|
+
|
|
338
|
+
for (let i = 0; i < this.layers.length; i++) {
|
|
339
|
+
const layer = this.layers[i]
|
|
340
|
+
const layerCommandList = layer.commandList = []
|
|
341
|
+
|
|
342
|
+
for (let pass = 0; pass < batchedCommandList.length; pass++) {
|
|
343
|
+
const offset = layer.offsets[pass], count = layer.counts[pass]
|
|
344
|
+
if (typeof offset !== 'number' || typeof count !== 'number') {
|
|
345
|
+
continue
|
|
346
|
+
}
|
|
347
|
+
const command = batchedCommandList[pass]
|
|
348
|
+
command.uniformMap.tileIdTexture = function () {
|
|
349
|
+
return tileset.tileIdTexture
|
|
350
|
+
}
|
|
351
|
+
command.uniformMap.tileId = function () {
|
|
352
|
+
return tileId.color
|
|
353
|
+
}
|
|
354
|
+
command.pass = Cesium.Pass.CESIUM_3D_TILE
|
|
355
|
+
//通过副本的 offset 和 count 指定图层的绘制范围
|
|
356
|
+
const layerCommand = Cesium.DrawCommand.shallowClone(command)
|
|
357
|
+
layerCommand.pass = Cesium.Pass.CESIUM_3D_TILE
|
|
358
|
+
layerCommand.renderState = renderState
|
|
359
|
+
layerCommand.layerType = 'fill'
|
|
360
|
+
layerCommand.offset = offset
|
|
361
|
+
layerCommand.count = count
|
|
362
|
+
layerCommandList.push(layerCommand)
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
//标记 drawCommand 创建完成
|
|
367
|
+
this.state = 'done'
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
update(frameState, tileset) {
|
|
371
|
+
if (!this.geometryInstances) {
|
|
372
|
+
return
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
super.update(frameState, tileset)
|
|
376
|
+
|
|
377
|
+
if (!this.primitive && this.geometryInstances.length) {
|
|
378
|
+
this.createPrimitive()
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (this.primitive && this.state !== 'done' && this.state !== 'error') {
|
|
382
|
+
//先保存系统的 commandList
|
|
383
|
+
const preCommandList = frameState.commandList
|
|
384
|
+
//临时覆盖 frameState.commandList,用于获取合批之后的drawCommand
|
|
385
|
+
const batchedCommandList = frameState.commandList = []
|
|
386
|
+
|
|
387
|
+
//执行 primitive 的 update ,直到生成了合批后的drawCommand
|
|
388
|
+
try {
|
|
389
|
+
this.primitive.update(frameState)
|
|
390
|
+
} catch (err) {//如果报错,下一帧就不要再执行 update 了,以免重复打印错误信息
|
|
391
|
+
this.geometryInstances = []
|
|
392
|
+
this.state = 'error'
|
|
393
|
+
if (err.stack) console.trace(err.stack)
|
|
394
|
+
else console.error(err);
|
|
395
|
+
return
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
//使用合批后的 drawCommand 创建副本,为渲染图层分配 drawCommand
|
|
399
|
+
if (batchedCommandList.length > 0) {
|
|
400
|
+
this.createLayerCommands(batchedCommandList, tileset)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
//恢复系统的 commandList
|
|
404
|
+
frameState.commandList = preCommandList
|
|
405
|
+
this.geometryInstances = []
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
destroy() {
|
|
410
|
+
this.primitive = this.primitive && this.primitive.destroy()
|
|
411
|
+
this._batchTable = null
|
|
412
|
+
this.geometryInstances = null
|
|
413
|
+
|
|
414
|
+
super.destroy()
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
isDestroyed() {
|
|
418
|
+
return false
|
|
419
|
+
}
|
|
420
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { VectorTileFeature } from "@mapbox/vector-tile";
|
|
2
|
+
import { IRenderLayer } from "../IRenderLayer";
|
|
3
|
+
import { VectorTileset } from "../../VectorTileset";
|
|
4
|
+
import { VectorTileLOD } from "../../VectorTileLOD";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 图层渲染器基类,负责瓦片内指定类型图层的合批几何体、批次表、绘图命令(DrawCommand)的构建,以及图层DrawCommand浅拷贝副本(shallow clone)的分配
|
|
8
|
+
* @see FillLayerVisualizer
|
|
9
|
+
* @see LineLayerVisualizer
|
|
10
|
+
* @see SymbolLayerVisualizer
|
|
11
|
+
*/
|
|
12
|
+
export class ILayerVisualizer {
|
|
13
|
+
/**
|
|
14
|
+
* 构造图层渲染器实例。图层渲染器负责瓦片内指定类型图层的合批几何体、批次表、绘图命令(DrawCommand)的构建,以及图层DrawCommand浅拷贝副本(shallow clone)的分配。
|
|
15
|
+
* 注意:构造函数仅供VectorTileLOD调用,请勿在其他模块直接调用
|
|
16
|
+
* @param {VectorTileLOD} tile
|
|
17
|
+
* @param {IRenderLayer[]} [layers]
|
|
18
|
+
* @inner
|
|
19
|
+
* @see FillLayerVisualizer
|
|
20
|
+
* @see LineLayerVisualizer
|
|
21
|
+
* @see SymbolLayerVisualizer
|
|
22
|
+
*/
|
|
23
|
+
constructor(tile, layers = []) {
|
|
24
|
+
/**
|
|
25
|
+
* @type {VectorTileLOD}
|
|
26
|
+
*/
|
|
27
|
+
this.tile = tile
|
|
28
|
+
/**
|
|
29
|
+
* @type {IRenderLayer[]}
|
|
30
|
+
*/
|
|
31
|
+
this.layers = layers
|
|
32
|
+
/**
|
|
33
|
+
* 图层渲染器状态
|
|
34
|
+
* @type {'none'|'done'|'error'}
|
|
35
|
+
*/
|
|
36
|
+
this.state = 'none'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 添加图层:将图层及其过滤后的要素添加到图层渲染器,子类实现该方法,完成图层存储、要素转换等合批构建需要的准备工作
|
|
41
|
+
* @param {VectorTileFeature[]} features
|
|
42
|
+
* @param {IRenderLayer} renderLayer
|
|
43
|
+
* @param {Cesium.frameState} frameState
|
|
44
|
+
* @param {VectorTileset} tileset
|
|
45
|
+
*/
|
|
46
|
+
addLayer(features, renderLayer, frameState, tileset) {
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 更新渲染器:子类实现该方法,完成合批几何体、批次表、绘图命令(DrawCommand)的构建,以及图层DrawCommand浅拷贝副本(shallow clone)的分配等工作
|
|
52
|
+
* @param {*} frameState
|
|
53
|
+
* @param {*} tileset
|
|
54
|
+
*/
|
|
55
|
+
update(frameState, tileset) {
|
|
56
|
+
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 销毁图层渲染器对象,释放资源
|
|
61
|
+
*/
|
|
62
|
+
destroy() {
|
|
63
|
+
this.tile = null
|
|
64
|
+
this.layers.length = 0
|
|
65
|
+
this.isDestroyed = function returnTrue() {
|
|
66
|
+
return true
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
isDestroyed() {
|
|
71
|
+
return false
|
|
72
|
+
}
|
|
73
|
+
}
|