UNPKG

maplibre-gl

Version:

BSD licensed community fork of mapbox-gl, a WebGL interactive maps library

113 lines (90 loc) • 4.11 kB
import {EXTENT} from '../../data/extent.ts'; import {type PreparedShader, shaders} from '../../shaders/shaders.ts'; import {Mesh} from '../../render/mesh.ts'; import {PosArray, TriangleIndexArray} from '../../data/array_types.g.ts'; import {SegmentVector} from '../../data/segment.ts'; import posAttributes from '../../data/pos_attributes.ts'; import {SubdivisionGranularitySetting} from '../../render/subdivision_granularity_settings.ts'; import {mercatorWorldCoordinateHelper} from '../mercator_coordinate.ts'; import type {ProjectionSpecification} from '@maplibre/maplibre-gl-style-spec'; import type {Context} from '../../webgl/context.ts'; import type {CanonicalTileID} from '../../tile/tile_id.ts'; import type {Projection, TileMeshUsage} from './projection.ts'; import type {WorldCoordinateHelper} from '../transform_interface.ts'; export const MercatorShaderDefine = '#define PROJECTION_MERCATOR'; export const MercatorShaderVariantKey = 'mercator'; /** * The flat projection. Mercator by default; the factory also builds one for a CRS registered with `addProjection`, * since such tiles already sit in their own quad grid and render exactly like mercator tiles do. The projection * takes its name from the lng/lat mapping of that grid, which the transform built alongside it runs on too. * Every planar projection shares one shader variant. */ export class MercatorProjection implements Projection { private _cachedMesh: Mesh = null; private readonly _worldCoordinateHelper: WorldCoordinateHelper; /** * @param worldCoordinateHelper - the lng/lat mapping of the grid this projection draws; mercator's when omitted */ constructor(worldCoordinateHelper: WorldCoordinateHelper = mercatorWorldCoordinateHelper) { this._worldCoordinateHelper = worldCoordinateHelper; } get name(): ProjectionSpecification['type'] { return this._worldCoordinateHelper.name; } get worldCoordinateHelper(): WorldCoordinateHelper { return this._worldCoordinateHelper; } get useSubdivision(): boolean { // Mercator never uses subdivision. return false; } get shaderVariantName(): string { return MercatorShaderVariantKey; } get shaderDefine(): string { return MercatorShaderDefine; } get shaderPreludeCode(): PreparedShader { return shaders.projectionMercator; } get vertexShaderPreludeCode(): string { return shaders.projectionMercator.vertexSource; } get subdivisionGranularity(): SubdivisionGranularitySetting { return SubdivisionGranularitySetting.noSubdivision; } get useGlobeControls(): boolean { return false; } get transitionState(): number { return 0; } public destroy(): void { // Do nothing. } public getMeshFromTileID(context: Context, _tileID: CanonicalTileID, _hasBorder: boolean, _allowPoles: boolean, _usage: TileMeshUsage): Mesh { if (this._cachedMesh) { return this._cachedMesh; } // The parameters tileID, hasBorder and allowPoles are all ignored on purpose for mercator meshes. const tileExtentArray = new PosArray(); tileExtentArray.emplaceBack(0, 0); tileExtentArray.emplaceBack(EXTENT, 0); tileExtentArray.emplaceBack(0, EXTENT); tileExtentArray.emplaceBack(EXTENT, EXTENT); const tileExtentBuffer = context.createVertexBuffer(tileExtentArray, posAttributes.members); const tileExtentSegments = SegmentVector.simpleSegment(0, 0, 4, 2); const quadTriangleIndices = new TriangleIndexArray(); quadTriangleIndices.emplaceBack(1, 0, 2); quadTriangleIndices.emplaceBack(1, 2, 3); const quadTriangleIndexBuffer = context.createIndexBuffer(quadTriangleIndices); this._cachedMesh = new Mesh(tileExtentBuffer, quadTriangleIndexBuffer, tileExtentSegments); return this._cachedMesh; } public recalculate(): void { // Do nothing. } public hasTransition(): boolean { return false; } }