mirror of
https://github.com/w3reality/three-geo.git
synced 2026-01-25 14:57:51 +00:00
190 lines
7.0 KiB
HTML
190 lines
7.0 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
|
<title>heightmap demo</title>
|
|
</head>
|
|
<body>
|
|
<canvas id="canvas" style="width: 100%; height: 100%;"></canvas>
|
|
<div id="mapWrapper" style="
|
|
position: absolute;
|
|
z-index: 100;
|
|
width: 520px; height: 320px;
|
|
top: 360px;
|
|
color: white;
|
|
background: #00000080;">
|
|
<div id="msg"></div>
|
|
<p><a style="color: white;" href="https://github.com/w3reality/three-geo/tree/master/examples/heightmaps">Source Code</a></p>
|
|
</div>
|
|
|
|
<script type="module">
|
|
import Stats from '../deps/three/examples/jsm/libs/stats.module.js';
|
|
import { OrbitControls } from '../deps/three/examples/jsm/controls/OrbitControls.js';
|
|
|
|
(async () => {
|
|
window.THREE = await import('../deps/three/build/three.module.js');
|
|
const Threelet = (await import('../deps/threelet.esm.js')).default;
|
|
const ThreeGeo = (await import('../../dist/three-geo.esm.js')).default;
|
|
|
|
//
|
|
|
|
const threelet = new Threelet({
|
|
canvas: document.getElementById("canvas"),
|
|
});
|
|
threelet.setup('mod-controls', OrbitControls);
|
|
threelet.setup('mod-stats', Stats, {panelType: 1});
|
|
|
|
const { scene, render } = threelet;
|
|
render(); // first time
|
|
|
|
//
|
|
|
|
const group = new THREE.Group();
|
|
group.rotation.x = - Math.PI/2;
|
|
scene.add(group);
|
|
|
|
const ioToken = 'pk.eyJ1IjoiamRldmVsIiwiYSI6ImNqemFwaGJoZjAyc3MzbXA1OGNuODBxa2EifQ.7M__SgfWZGJuEiSqbBXdoQ';
|
|
const tgeo = new ThreeGeo({
|
|
// tokenMapbox: '********', // <---- set your Mapbox API token here
|
|
tokenMapbox: ioToken,
|
|
});
|
|
|
|
const isDebug = 0;
|
|
if (isDebug) {
|
|
tgeo.tokenMapbox = 'zzzz';
|
|
tgeo.setApiVector(`../geo-viewer/cache/eiger/custom-terrain-vector`);
|
|
tgeo.setApiRgb(`../geo-viewer/cache/eiger/custom-terrain-rgb`);
|
|
tgeo.setApiSatellite(`../geo-viewer/cache/eiger/custom-satellite`);
|
|
}
|
|
|
|
const createTextSprite = (text, color) => Threelet.Utils.createCanvasSprite(
|
|
Threelet.Utils.createCanvasFromText(text, 256, 64, {
|
|
tfg: color,
|
|
fontSize: '36px',
|
|
fontFamily: 'Times',
|
|
}));
|
|
|
|
const demToObjects = (demUri, demTile, proj) => {
|
|
const { obj, offset, size } = ThreeGeo.Utils.bboxToWireframe(
|
|
ThreeGeo.Utils.tileToBbox(demTile), proj, {
|
|
offsetZ: - 0.1,
|
|
color: 0xcc00cc,
|
|
});
|
|
// console.log('offset, size:', offset, size);
|
|
|
|
let _demUri = demUri;
|
|
if (isDebug) {
|
|
const [tx, ty, tz] = demTile;
|
|
_demUri = `../geo-viewer/cache/eiger/custom-terrain-rgb-${tz}-${tx}-${ty}.png`;
|
|
}
|
|
|
|
const plane = new THREE.Mesh(
|
|
new THREE.PlaneGeometry(size[0], size[1]),
|
|
new THREE.MeshBasicMaterial({
|
|
map: new THREE.TextureLoader().load(_demUri),
|
|
// side: THREE.DoubleSide,
|
|
}));
|
|
plane.position.set(...offset);
|
|
|
|
const sp = createTextSprite(`${demTile.join('-')}`, '#f0f');
|
|
sp.position.set(offset[0], offset[1], offset[2] + 0.1);
|
|
|
|
return {
|
|
wireframe: obj,
|
|
plane: plane,
|
|
sprite: sp,
|
|
};
|
|
};
|
|
|
|
const msg = document.getElementById('msg');
|
|
const appendText = (el, text) => {
|
|
const div = document.createElement('div');
|
|
div.appendChild(document.createTextNode(text));
|
|
el.appendChild(div);
|
|
};
|
|
|
|
if (tgeo.tokenMapbox === ioToken && window.location.origin !== 'https://w3reality.github.io') {
|
|
const warning = 'Please set your Mapbox API token in the ThreeGeo constructor.';
|
|
appendText(msg, warning);
|
|
throw warning;
|
|
}
|
|
|
|
// params: [lat, lng], terrain's radius (km), zoom resolution, callbacks
|
|
// Beware the value of radius; radius > 5.0 (km) could trigger huge number of tile API calls!!
|
|
const origin = [46.5763, 7.9904];
|
|
const radius = 5.0;
|
|
const { proj, bbox, unitsPerMeter } = tgeo.getProjection(origin, radius);
|
|
// console.log('proj:', proj);
|
|
// console.log('unitsPerMeter:', unitsPerMeter);
|
|
|
|
const srcDemUris = {};
|
|
|
|
appendText(msg, `---- ROI ----`);
|
|
appendText(msg, `lat lng: (${origin[0]}, ${origin[1]})`);
|
|
appendText(msg, `radius: ${radius} [km]`);
|
|
appendText(msg, `units per km: ${unitsPerMeter * 1000}`);
|
|
appendText(msg, `bbox (w, s, e, n): (${bbox.map(q => q.toFixed(4)).join(', ')})`);
|
|
appendText(msg, `---- Terrain Composition ----`);
|
|
|
|
const appendCompositionInfo = (el, tile, srcDemTile) => {
|
|
const div = document.createElement('div');
|
|
el.appendChild(div);
|
|
|
|
let span = document.createElement('span');
|
|
span.style.color = '#00ffffff';
|
|
span.appendChild(document.createTextNode(`tile ${tile.join('-')}`));
|
|
div.appendChild(span);
|
|
|
|
div.appendChild(document.createTextNode(' using '));
|
|
|
|
span = document.createElement('span');
|
|
span.style.color = '#ff00ffff';
|
|
span.appendChild(document.createTextNode(`DEM ${srcDemTile.join('-')}`));
|
|
div.appendChild(span);
|
|
};
|
|
|
|
//
|
|
|
|
const terrain = await tgeo.getTerrainRgb(origin, radius, 12);
|
|
group.add(terrain);
|
|
|
|
terrain.children.forEach(mesh => {
|
|
mesh.material.wireframe = true;
|
|
|
|
console.log('rgb DEM mesh:', mesh);
|
|
console.log('userData:', mesh.userData);
|
|
|
|
//======== how to access the post-processed heightmap
|
|
const array = mesh.geometry.attributes.position.array;
|
|
console.log('array.length:', array.length); // 3x128x128 (+ deltaSeams)
|
|
|
|
//======== how to visualize constituent tiles of the terrain
|
|
const tile = mesh.userData.threeGeo.tile;
|
|
const { obj, offset } = ThreeGeo.Utils.bboxToWireframe(
|
|
ThreeGeo.Utils.tileToBbox(tile), proj, {offsetZ: - 0.05});
|
|
|
|
const sp = createTextSprite(`${tile.join('-')}`, '#0ff');
|
|
sp.position.set(offset[0], offset[1], offset[2] + 0.05);
|
|
group.add(obj, sp);
|
|
|
|
//======== how to access src DEM being used (grand-parental tile)
|
|
// ref - https://www.mapbox.com/help/access-elevation-data/#mapbox-terrain-rgb
|
|
const { tile: srcDemTile, uri: srcDemUri } =
|
|
mesh.userData.threeGeo.srcDem;
|
|
appendCompositionInfo(msg, tile, srcDemTile);
|
|
|
|
if (! srcDemUris[srcDemUri]) {
|
|
srcDemUris[srcDemUri] = true;
|
|
|
|
const { wireframe, plane, sprite } =
|
|
demToObjects(srcDemUri, srcDemTile, proj);
|
|
group.add(wireframe, plane, sprite);
|
|
}
|
|
});
|
|
|
|
render();
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|