@polygonjs/plugin-mapbox
Version:
Mapbox plugin for the 3D engine https://polygonjs.com
146 lines (145 loc) • 5.65 kB
JavaScript
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}`;
}
}