Skip to content

Instantly share code, notes, and snippets.

@ChaseIngebritson
Last active May 31, 2023 21:52
Show Gist options
  • Save ChaseIngebritson/22803b340664becdc08b03683e9f935d to your computer and use it in GitHub Desktop.
Save ChaseIngebritson/22803b340664becdc08b03683e9f935d to your computer and use it in GitHub Desktop.
Convert a Mapbox RGB tile to a ThreeJS Mesh
import { PlaneGeometry, DoubleSide, MeshBasicMaterial, Mesh, TextureLoader } from 'three';
const MAPBOX_TOKEN = 'Your token';
async function tileToMesh(x: number, y: number, z: number) {
const url = `https://api.mapbox.com/v4/mapbox.terrain-rgb/${z}/${x}/${y}.pngraw?access_token=${MAPBOX_TOKEN}`;
const pixels = await this.getPixels(url);
const planeSize = Math.sqrt(pixels.length / 4);
const geometry = new PlaneGeometry(planeSize, planeSize, planeSize - 1, planeSize - 1);
for (let i = 0; i < pixels.length; i += 4) {
const r = pixels[i + 0];
const g = pixels[i + 1];
const b = pixels[i + 2];
const height = this.rgbToHeight(r, g, b);
if (!geometry.vertices[i / 4]) {
console.error(`No vertices at index ${i / 4} found.`);
break;
}
geometry.vertices[i / 4].z = height;
}
geometry.verticesNeedUpdate = true;
const texture = new TextureLoader().load(url);
const material = new MeshBasicMaterial({ map: texture, side: DoubleSide, wireframe: true });
const mesh = new Mesh(geometry, material);
return mesh;
}
function getPixels(url: string): Promise<Uint8ClampedArray> {
return new Promise ((resolve, reject) => {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const img = new Image();
img.crossOrigin = 'Anonymous';
img.src = url;
img.onload = () => {
canvas.width = img.width;
canvas.height = img.width;
context.drawImage(img, 0, 0, img.width, img.width);
const imgData = context.getImageData(0, 0, img.width, img.height);
resolve(imgData.data);
};
});
}
function rgbToHeight(r: number, g: number, b: number) {
return -10000 + ((r * 256 * 256 + g * 256 + b) * 0.1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment