UNPKG

@polygonjs/plugin-mapbox

Version:

Mapbox plugin for the 3D engine https://polygonjs.com

146 lines (145 loc) 5.65 kB
import { LinearFilter, FloatType, RGBAFormat } from "three"; import { DataTexture } from "three"; import { TypedCopNode } from "@polygonjs/polygonjs/dist/src/engine/nodes/cop/_Base"; import { CoreMapboxUtils } from "../../../core/mapbox/Utils"; import { CoreImage } from "@polygonjs/polygonjs/dist/src/core/Image"; import { CoreMapboxClient } from "../../../core/mapbox/Client"; export var TileType = /* @__PURE__ */ ((TileType2) => { TileType2["ELEVATION"] = "elevation"; TileType2["SATELLITE"] = "satellite"; return TileType2; })(TileType || {}); const TILE_TYPES = ["elevation" /* ELEVATION */, "satellite" /* SATELLITE */]; export var TileRes = /* @__PURE__ */ ((TileRes2) => { TileRes2[TileRes2["LOW"] = 256] = "LOW"; TileRes2[TileRes2["HIGH"] = 512] = "HIGH"; return TileRes2; })(TileRes || {}); const ROOT_URL = "https://api.mapbox.com/v4"; import { NodeParamsConfig, ParamConfig } from "@polygonjs/polygonjs/dist/src/engine/nodes/utils/params/ParamsConfig"; class MapboxTileCopParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); this.lngLat = ParamConfig.VECTOR2([-119.63, 37.73311]); this.zoom = ParamConfig.INTEGER(12, { range: [1, 24], rangeLocked: [true, true] }); this.type = ParamConfig.INTEGER(0, { menu: { entries: TILE_TYPES.map((m) => ({ name: m, value: TILE_TYPES.indexOf(m) })) } }); } } const ParamsConfig = new MapboxTileCopParamsConfig(); export class MapboxTileCopNode extends TypedCopNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; this._paramHires = true; this._texture = new DataTexture(new Float32Array(4 * 512 /* HIGH */ * 512 /* HIGH */), 512 /* HIGH */, 512 /* HIGH */, RGBAFormat, FloatType); } static type() { return "mapboxTile"; } initializeNode() { this._texture.image.data.fill(255); this._texture.minFilter = LinearFilter; this._texture.magFilter = LinearFilter; this._texture.flipY = true; } async cook() { const type = TILE_TYPES[this.pv.type]; switch (type) { case "elevation" /* ELEVATION */: { await this._cookForElevation(); break; } case "satellite" /* SATELLITE */: { await this._cookForSatellite(); break; } } this._texture.needsUpdate = true; this.setTexture(this._texture); } async _cookForElevation() { const url = await this._url("mapbox.terrain-rgb"); const image_data_rgba = await CoreImage.data_from_url(url); const data_rgba = image_data_rgba.data; const pixels_count = image_data_rgba.width * image_data_rgba.height; let src_stride, dest_stride; const dest_data = this._texture.image.data; if (this._paramHires) { let elevation, R, G, B; for (let i = 0; i < pixels_count; i++) { src_stride = i * 4; dest_stride = i * 4; R = data_rgba[src_stride + 0]; G = data_rgba[src_stride + 1]; B = data_rgba[src_stride + 2]; elevation = (R * 256 * 256 + G * 256 + B) * 0.1 / (256 * 256); dest_data[dest_stride + 0] = elevation; dest_data[dest_stride + 1] = elevation; dest_data[dest_stride + 2] = elevation; } } } async _cookForSatellite() { const url = await this._url("mapbox.satellite"); const image_data_rgba = await CoreImage.data_from_url(url); const data_rgba = image_data_rgba.data; const pixels_count = image_data_rgba.width * image_data_rgba.height; let src_stride, dest_stride; const dest_data = this._texture.image.data; if (this._paramHires) { for (let i = 0; i < pixels_count; i++) { src_stride = i * 4; dest_stride = i * 4; dest_data[dest_stride + 0] = data_rgba[src_stride + 0] / 255; dest_data[dest_stride + 1] = data_rgba[src_stride + 1] / 255; dest_data[dest_stride + 2] = data_rgba[src_stride + 2] / 255; } } else { const resolution = 256 /* LOW */; for (let i = 0; i < resolution; i++) { for (let j = 0; j < resolution; j++) { let k = i * resolution + j; src_stride = k * 4; dest_stride = k * 4; dest_data[dest_stride + 0] = data_rgba[src_stride + 0]; dest_data[dest_stride + 1] = data_rgba[src_stride + 1]; dest_data[dest_stride + 2] = data_rgba[src_stride + 2]; k = (i + 1) * resolution + j; dest_stride = k * 4; dest_data[dest_stride + 0] = data_rgba[src_stride + 0]; dest_data[dest_stride + 1] = data_rgba[src_stride + 1]; dest_data[dest_stride + 2] = data_rgba[src_stride + 2]; k = i * resolution + (j + 1); dest_stride = k * 4; dest_data[dest_stride + 0] = data_rgba[src_stride + 0]; dest_data[dest_stride + 1] = data_rgba[src_stride + 1]; dest_data[dest_stride + 2] = data_rgba[src_stride + 2]; k = (i + 1) * resolution + (j + 1); dest_stride = k * 4; dest_data[dest_stride + 0] = data_rgba[src_stride + 0]; dest_data[dest_stride + 1] = data_rgba[src_stride + 1]; dest_data[dest_stride + 2] = data_rgba[src_stride + 2]; } } } } async _url(endpoint) { const tile_number = CoreMapboxUtils.lnglat_to_tile_number(this.pv.lngLat.x, this.pv.lngLat.y, this.pv.zoom); const x = tile_number.x; const y = tile_number.y; const z = this.pv.zoom; const res = this._paramHires ? "@2x" : ""; const token = CoreMapboxClient.token(); return `${ROOT_URL}/${endpoint}/${z}/${x}/${y}${res}.pngraw?access_token=${token}`; } }