Display Google Maps 3D Tiles using Giro3D and 3d-tiles-renderer
.
This example requires a Google Maps API key. You can register this key directly in the URL by appending ?key=THE_KEY
in the URL, or enter the key in the text box.
import { Vector3 } from "three";
import { GlobeControls } from "3d-tiles-renderer";
import {
GoogleCloudAuthPlugin,
TileCompressionPlugin,
UpdateOnChangePlugin,
UnloadTilesPlugin,
TilesFadePlugin,
} from "3d-tiles-renderer/plugins";
import Instance from "@giro3d/giro3d/core/Instance.js";
import Tiles3D from "@giro3d/giro3d/entities/Tiles3D.js";
import Inspector from "@giro3d/giro3d/gui/Inspector.js";
function run(apiKey) {
const instance = new Instance({
target: "view",
crs: "EPSG:4978",
backgroundColor: "black",
});
// Note that we need the DRACO and Basis libraries.
// You can omit those parameters to use the default URLs which use a CDN.
const entity = new Tiles3D({
dracoDecoderPath: "/assets/wasm/",
ktx2DecoderPath: "/assets/wasm/",
});
const tiles = entity.tiles;
const view = instance.view;
view.minNearPlane = 200;
const camera = view.camera;
camera.up = new Vector3(0, 0, 1);
camera.position.set(30_000_000, 0, 0);
camera.lookAt(0, 0, 0);
camera.updateMatrixWorld();
tiles.registerPlugin(
new GoogleCloudAuthPlugin({ apiToken: apiKey, autoRefreshToken: true }),
);
tiles.registerPlugin(new TileCompressionPlugin());
tiles.registerPlugin(new UpdateOnChangePlugin());
tiles.registerPlugin(new UnloadTilesPlugin());
tiles.registerPlugin(new TilesFadePlugin());
const controls = new GlobeControls(
instance.scene,
camera,
instance.domElement,
tiles,
);
controls.enableDamping = true;
const attributions = [];
function updateAttributions() {
attributions.length = 0;
entity.tiles.getAttributions(attributions);
const text = attributions.map((a) => a.value).join(",");
StatusBar.setAttributionHtml(`© ${text}`);
}
function animate() {
const altitude = controls.getDistanceToCenter() - 6_400_000;
if (altitude > 100_000) {
view.minNearPlane = 2000;
} else if (altitude > 1_000) {
view.minNearPlane = 200;
} else {
view.minNearPlane = 2;
}
controls.update();
instance.notifyChange(entity);
updateAttributions();
requestAnimationFrame(animate);
}
animate();
controls.update();
instance.add(entity);
Inspector.attach("inspector", instance);
}
const url = new URL(document.URL);
let key = url.searchParams.get("key");
if (key != null) {
run(key);
} else {
document.getElementById("warning").style.display = "block";
}
document.getElementById("start").onclick = () => {
const enteredKey = document.getElementById("googleApiKey").value;
if (enteredKey != null) {
const url = new URL(document.URL);
url.searchParams.delete("key");
url.searchParams.append("key", enteredKey);
window.history.replaceState({}, null, url.toString());
run(enteredKey);
document.getElementById("warning").style.display = "none";
}
};
<!doctype html>
<html lang="en">
<head>
<title>Google Photorealistic 3D Tiles</title>
<meta charset="UTF-8" />
<meta name="name" content="google_photorealistic_3d_tiles" />
<meta
name="description"
content="Display Google Maps 3D Tiles using Giro3D and <a href="https://github.com/NASA-AMMOS/3DTilesRendererJS" target="_blank"><code>3d-tiles-renderer</code></a>."
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="https://giro3d.org/images/favicon.svg" />
<link
href="https://giro3d.org/assets/bootstrap-custom.css"
rel="stylesheet"
/>
<script src="https://giro3d.org/assets/bootstrap.bundle.min.js"></script>
<link
rel="stylesheet"
type="text/css"
href="https://giro3d.org/latest/examples/css/example.css"
/>
</head>
<body>
<div id="view" class="m-0 p-0 w-100 h-100"></div>
<div
id="inspector"
class="position-absolute top-0 start-0 mh-100 overflow-auto"
></div>
<div
class="position-absolute top-50 start-50 translate-middle text-center"
style="display: none"
id="warning"
>
No Google Maps API key registered.<br />You can register this key directly
in the URL by appending <code>?key=THE_KEY</code> in the URL,<br />or
enter the key in the text box and press 'Reload'.
</div>
<div class="side-pane-with-status-bar">
<div class="input-group">
<input
type="text"
class="form-control"
id="googleApiKey"
placeholder="Google Tiles API key"
/>
<button class="btn btn-primary" id="start">Reload</button>
</div>
</div>
<script type="module" src="index.js"></script>
<script>
/* activate popovers */
const popoverTriggerList = [].slice.call(
document.querySelectorAll('[data-bs-toggle="popover"]'),
);
popoverTriggerList.map(
// bootstrap is used as script in the template, disable warning about undef
// eslint-disable-next-line no-undef
(popoverTriggerEl) =>
new bootstrap.Popover(popoverTriggerEl, {
trigger: "hover",
placement: "left",
content: document.getElementById(
popoverTriggerEl.getAttribute("data-bs-content"),
).innerHTML,
html: true,
}),
);
</script>
</body>
</html>
{
"name": "google_photorealistic_3d_tiles",
"dependencies": {
"@giro3d/giro3d": "0.42.1"
},
"devDependencies": {
"vite": "^3.2.3"
},
"scripts": {
"start": "vite",
"build": "vite build"
}
}