UNPKG

mapbox-gl

Version:
132 lines (115 loc) 5.16 kB
'use strict'; const ProgramConfiguration = require('./program_configuration'); const createVertexArrayType = require('./vertex_array_type'); class Segment { constructor(vertexOffset, primitiveOffset) { this.vertexOffset = vertexOffset; this.primitiveOffset = primitiveOffset; this.vertexLength = 0; this.primitiveLength = 0; } } /** * A class that manages vertex and element arrays for a bucket. It handles initialization, * serialization for transfer to the main thread, and certain intervening mutations. * * A group has: * * * A "layout" vertex array, with fixed attributes, containing values calculated from layout properties. * * Zero, one, or two element arrays, with fixed layout, for eventual `gl.drawElements` use. * * Zero or more "paint" vertex arrays keyed by layer ID, each with a dynamic layout which depends * on which paint properties of that layer use data-driven-functions (property functions or * property-and-zoom functions). Values are calculated by evaluating those functions. * * Because indexed rendering is best done with 16 bit indices (and in fact, in WebGL, 16 bit * indices are the only choice), a form of segmented addressing is used. Each group * contains an `Array` of `Segment`s. A segment contains a vertex array offset, which forms * the "base address" of indices within this segment. Each segment is drawn separately. * * @private */ class ArrayGroup { constructor(programInterface, layers, zoom) { this.globalProperties = {zoom}; const LayoutVertexArrayType = createVertexArrayType(programInterface.layoutAttributes); this.layoutVertexArray = new LayoutVertexArrayType(); const ElementArrayType = programInterface.elementArrayType; if (ElementArrayType) this.elementArray = new ElementArrayType(); const ElementArrayType2 = programInterface.elementArrayType2; if (ElementArrayType2) this.elementArray2 = new ElementArrayType2(); this.layerData = {}; for (const layer of layers) { const programConfiguration = ProgramConfiguration.createDynamic( programInterface.paintAttributes || [], layer, zoom); this.layerData[layer.id] = { layer: layer, programConfiguration: programConfiguration, paintVertexArray: new programConfiguration.PaintVertexArray(), paintPropertyStatistics: programConfiguration.createPaintPropertyStatistics() }; } this.segments = []; this.segments2 = []; } prepareSegment(numVertices) { let segment = this.segments[this.segments.length - 1]; if (!segment || segment.vertexLength + numVertices > ArrayGroup.MAX_VERTEX_ARRAY_LENGTH) { segment = new Segment(this.layoutVertexArray.length, this.elementArray.length); this.segments.push(segment); } return segment; } prepareSegment2(numVertices) { let segment = this.segments2[this.segments2.length - 1]; if (!segment || segment.vertexLength + numVertices > ArrayGroup.MAX_VERTEX_ARRAY_LENGTH) { segment = new Segment(this.layoutVertexArray.length, this.elementArray2.length); this.segments2.push(segment); } return segment; } populatePaintArrays(featureProperties) { for (const key in this.layerData) { const layerData = this.layerData[key]; if (layerData.paintVertexArray.bytesPerElement === 0) continue; layerData.programConfiguration.populatePaintArray( layerData.layer, layerData.paintVertexArray, layerData.paintPropertyStatistics, this.layoutVertexArray.length, this.globalProperties, featureProperties); } } isEmpty() { return this.layoutVertexArray.length === 0; } serialize(transferables) { return { layoutVertexArray: this.layoutVertexArray.serialize(transferables), elementArray: this.elementArray && this.elementArray.serialize(transferables), elementArray2: this.elementArray2 && this.elementArray2.serialize(transferables), paintVertexArrays: serializePaintVertexArrays(this.layerData, transferables), segments: this.segments, segments2: this.segments2 }; } } function serializePaintVertexArrays(layerData, transferables) { const paintVertexArrays = {}; for (const layerId in layerData) { const inputArray = layerData[layerId].paintVertexArray; if (inputArray.length === 0) continue; const array = inputArray.serialize(transferables); const type = inputArray.constructor.serialize(); paintVertexArrays[layerId] = {array, type}; } return paintVertexArrays; } /** * The maximum size of a vertex array. This limit is imposed by WebGL's 16 bit * addressing of vertex buffers. * @private * @readonly */ ArrayGroup.MAX_VERTEX_ARRAY_LENGTH = Math.pow(2, 16) - 1; module.exports = ArrayGroup;