Kartu 3D Fotorealistik menggunakan format glTF standar OGC, yang berarti Anda dapat menggunakan perender apa pun yang mendukung spesifikasi Kartu 3D OGC untuk membuat visualisasi 3D. Misalnya, Cesium adalah library open source dasar untuk merender visualisasi 3D.
Menggunakan CesiumJS
CesiumJS adalah library JavaScript open source untuk visualisasi 3D di web. Untuk informasi selengkapnya tentang penggunaan CesiumJS, lihat Mempelajari CesiumJS.
Kontrol pengguna
Perender ubin CesiumJS memiliki kumpulan kontrol pengguna standar.
Tindakan | Deskripsi |
---|---|
Tampilan geser | Klik kiri & tarik |
Tampilan zoom | Klik kanan & tarik, atau scroll roda mouse |
Memutar tampilan | Ctrl + klik kiri/kanan & tarik, atau klik tengah & tarik |
Praktik terbaik
Ada beberapa pendekatan yang dapat Anda lakukan untuk mengurangi waktu pemuatan 3D CesiumJS. Contoh:
Aktifkan permintaan serentak dengan menambahkan pernyataan berikut ke HTML rendering Anda:
Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = <REQUEST_COUNT>
Makin tinggi
REQUEST_COUNT
, makin cepat kartu dimuat. Namun, saat memuat di browser Chrome denganREQUEST_COUNT
lebih besar dari 10 dan cache dinonaktifkan, Anda mungkin mengalami masalah Chrome umum. Untuk sebagian besar kasus penggunaan, sebaiknya gunakanREQUEST_COUNT
18 untuk performa optimal.Mengaktifkan tingkat detail yang dilewati. Untuk mengetahui informasi selengkapnya, lihat masalah Cesium ini.
Pastikan Anda menampilkan atribusi data dengan benar dengan mengaktifkan
showCreditsOnScreen: true
. Untuk mengetahui informasi selengkapnya, lihat
Kebijakan.
Metrik rendering
Untuk menemukan kecepatan frame, lihat frekuensi panggilan metode requestAnimationFrame per detik.
Untuk melihat cara penghitungan latensi frame, lihat class PerformanceDisplay.
Contoh perender CesiumJS
Anda dapat menggunakan perender CesiumJS dengan Kartu 3D Map Tiles API dengan hanya menyediakan URL set kartu root.
Contoh sederhana
Contoh berikut menginisialisasi perender CesiumJS, lalu memuat tileset root.
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<title>CesiumJS 3D Tiles Simple Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Cesium.js"></script>
<link href="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
<div id="cesiumContainer"></div>
<script>
// Enable simultaneous requests.
Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = 18;
// Create the viewer.
const viewer = new Cesium.Viewer('cesiumContainer', {
imageryProvider: false,
baseLayerPicker: false,
geocoder: false,
globe: false,
// https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/#enabling-request-render-mode
requestRenderMode: true,
});
// Add 3D Tiles tileset.
const tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: "https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY",
// This property is needed to appropriately display attributions
// as required.
showCreditsOnScreen: true,
}));
</script>
</body>
Untuk informasi tentang requestRenderMode
, lihat
Mengaktifkan mode render permintaan.
Halaman HTML dirender seperti yang ditunjukkan di sini.
Integrasi Places API
Anda dapat menggunakan CesiumJS dengan Places API untuk mengambil informasi selengkapnya. Anda dapat menggunakan widget Autocomplete untuk membuka area pandang Places. Contoh ini menggunakan Places Autocomplete API, yang diaktifkan dengan mengikuti petunjuk ini, dan Maps JavaScript API, yang diaktifkan dengan mengikuti petunjuk ini.
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>CesiumJS 3D Tiles Places API Integration Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Cesium.js"></script>
<link href="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
<label for="pacViewPlace">Go to a place: </label>
<input
type="text"
id="pacViewPlace"
name="pacViewPlace"
placeholder="Enter a location..."
style="width: 300px"
/>
<div id="cesiumContainer"></div>
<script>
// Enable simultaneous requests.
Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = 18;
// Create the viewer.
const viewer = new Cesium.Viewer("cesiumContainer", {
imageryProvider: false,
baseLayerPicker: false,
requestRenderMode: true,
geocoder: false,
globe: false,
});
// Add 3D Tiles tileset.
const tileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: "https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY",
// This property is required to display attributions as required.
showCreditsOnScreen: true,
})
);
const zoomToViewport = (viewport) => {
viewer.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArray([
viewport.getNorthEast().lng(), viewport.getNorthEast().lat(),
viewport.getSouthWest().lng(), viewport.getNorthEast().lat(),
viewport.getSouthWest().lng(), viewport.getSouthWest().lat(),
viewport.getNorthEast().lng(), viewport.getSouthWest().lat(),
viewport.getNorthEast().lng(), viewport.getNorthEast().lat(),
]),
width: 10,
clampToGround: true,
material: Cesium.Color.RED,
},
});
viewer.flyTo(viewer.entities);
};
function initAutocomplete() {
const autocomplete = new google.maps.places.Autocomplete(
document.getElementById("pacViewPlace"),
{
fields: [
"geometry",
"name",
],
}
);
autocomplete.addListener("place_changed", () => {
viewer.entities.removeAll();
const place = autocomplete.getPlace();
if (!place.geometry || !place.geometry.viewport) {
window.alert("No viewport for input: " + place.name);
return;
}
zoomToViewport(place.geometry.viewport);
});
}
</script>
<script
async=""
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initAutocomplete"
></script>
</body>
Memutar tampilan drone
Anda dapat mengontrol kamera untuk menganimasikan melalui tileset. Jika digabungkan dengan Places API dan Elevation API, animasi ini akan menyimulasikan flyover drone interaktif dari lokasi menarik apa pun.
Contoh kode ini akan membawa Anda ke tempat yang Anda pilih di widget Autocomplete.
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>CesiumJS 3D Tiles Rotating Drone View Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Cesium.js"></script>
<link href="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
<label for="pacViewPlace">Go to a place: </label>
<input type="text" id="pacViewPlace" name="pacViewPlace" placeholder="Enter a location..." style="width: 300px" />
<div id="cesiumContainer"></div>
<script>
// Enable simultaneous requests.
Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = 18;
// Create the viewer and remove unneeded options.
const viewer = new Cesium.Viewer("cesiumContainer", {
imageryProvider: false,
baseLayerPicker: false,
homeButton: false,
fullscreenButton: false,
navigationHelpButton: false,
vrButton: false,
sceneModePicker: false,
geocoder: false,
globe: false,
infobox: false,
selectionIndicator: false,
timeline: false,
projectionPicker: false,
clockViewModel: null,
animation: false,
requestRenderMode: true,
});
// Add 3D Tile set.
const tileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: "https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY",
// This property is required to display attributions.
showCreditsOnScreen: true,
})
);
// Point the camera at a location and elevation, at a viewport-appropriate distance.
function pointCameraAt(location, viewport, elevation) {
const distance = Cesium.Cartesian3.distance(
Cesium.Cartesian3.fromDegrees(
viewport.getSouthWest().lng(), viewport.getSouthWest().lat(), elevation),
Cesium.Cartesian3.fromDegrees(
viewport.getNorthEast().lng(), viewport.getNorthEast().lat(), elevation)
) / 2;
const target = new Cesium.Cartesian3.fromDegrees(location.lng(), location.lat(), elevation);
const pitch = -Math.PI / 4;
const heading = 0;
viewer.camera.lookAt(target, new Cesium.HeadingPitchRange(heading, pitch, distance));
}
// Rotate the camera around a location and elevation, at a viewport-appropriate distance.
let unsubscribe = null;
function rotateCameraAround(location, viewport, elevation) {
if(unsubscribe) unsubscribe();
pointCameraAt(location, viewport, elevation);
unsubscribe = viewer.clock.onTick.addEventListener(() => {
viewer.camera.rotate(Cesium.Cartesian3.UNIT_Z);
});
}
function initAutocomplete() {
const autocomplete = new google.maps.places.Autocomplete(
document.getElementById("pacViewPlace"), {
fields: [
"geometry",
"name",
],
}
);
autocomplete.addListener("place_changed", async () => {
const place = autocomplete.getPlace();
if (!(place.geometry && place.geometry.viewport && place.geometry.location)) {
window.alert(`Insufficient geometry data for place: ${place.name}`);
return;
}
// Get place elevation using the ElevationService.
const elevatorService = new google.maps.ElevationService();
const elevationResponse = await elevatorService.getElevationForLocations({
locations: [place.geometry.location],
});
if(!(elevationResponse.results && elevationResponse.results.length)){
window.alert(`Insufficient elevation data for place: ${place.name}`);
return;
}
const elevation = elevationResponse.results[0].elevation || 10;
rotateCameraAround(
place.geometry.location,
place.geometry.viewport,
elevation
);
});
}
</script>
<script async src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initAutocomplete"></script>
</body>
Menggambar polyline dan label
Contoh kode ini menunjukkan cara menambahkan polyline dan label ke peta. Anda dapat menambahkan polyline ke peta untuk menampilkan rute mobil dan jalan kaki, atau untuk menampilkan batas properti, atau untuk menghitung durasi berkendara dan berjalan kaki. Anda juga dapat mendapatkan atribut tanpa benar-benar merender tampilan.
Anda dapat mengajak pengguna melakukan tur yang diseleksi di lingkungan sekitar, atau menampilkan properti tetangga yang saat ini sedang dijual, lalu menambahkan objek 3D seperti papan reklame ke tampilan.
Anda dapat meringkas perjalanan, mencantumkan properti yang Anda lihat, dan menampilkan detail ini dalam objek virtual.
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>CesiumJS 3D Tiles Polyline and Label Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Cesium.js"></script>
<link
href="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"
/>
</head>
<body>
<div id="cesiumContainer"></div>
<script>
// Enable simultaneous requests.
Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = 18;
// Create the viewer.
const viewer = new Cesium.Viewer("cesiumContainer", {
imageryProvider: false,
baseLayerPicker: false,
requestRenderMode: true,
geocoder: false,
globe: false,
});
// Add 3D Tiles tileset.
const tileset = viewer.scene.primitives.add(
new Cesium.Cesium3DTileset({
url: "https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY",
// This property is required to display attributions as required.
showCreditsOnScreen: true,
})
);
// Draws a circle at the position, and a line from the previous position.
const drawPointAndLine = (position, prevPosition) => {
viewer.entities.removeAll();
if (prevPosition) {
viewer.entities.add({
polyline: {
positions: [prevPosition, position],
width: 3,
material: Cesium.Color.WHITE,
clampToGround: true,
classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
},
});
}
viewer.entities.add({
position: position,
ellipsoid: {
radii: new Cesium.Cartesian3(1, 1, 1),
material: Cesium.Color.RED,
},
});
};
// Compute, draw, and display the position's height relative to the previous position.
var prevPosition;
const processHeights = (newPosition) => {
drawPointAndLine(newPosition, prevPosition);
const newHeight = Cesium.Cartographic.fromCartesian(newPosition).height;
let labelText = "Current altitude (meters above sea level):\n\t" + newHeight;
if (prevPosition) {
const prevHeight =
Cesium.Cartographic.fromCartesian(prevPosition).height;
labelText += "\nHeight from previous point (meters):\n\t" + Math.abs(newHeight - prevHeight);
}
viewer.entities.add({
position: newPosition,
label: {
text: labelText,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
pixelOffset: new Cesium.Cartesian2(0, -10),
showBackground: true,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
}
});
prevPosition = newPosition;
};
const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
handler.setInputAction(function (event) {
const earthPosition = viewer.scene.pickPosition(event.position);
if (Cesium.defined(earthPosition)) {
processHeights(earthPosition);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
</script>
</body>
Orbit kamera
Di Cesium, Anda dapat mengorbitkan kamera di sekitar lokasi menarik, sehingga menghindari tabrakan dengan bangunan. Atau, Anda dapat membuat bangunan menjadi transparan saat kamera bergerak melaluinya.
Pertama, kunci kamera ke suatu titik, lalu Anda dapat membuat orbit kamera untuk
menampilkan aset. Anda dapat melakukannya dengan menggunakan fungsi
lookAtTransform
kamera dengan pemroses peristiwa, seperti yang ditunjukkan dalam contoh kode ini.
// Lock the camera onto a point.
const center = Cesium.Cartesian3.fromRadians(
2.4213211833389243,
0.6171926869414084,
3626.0426275055174
);
const transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);
viewer.scene.camera.lookAtTransform(
transform,
new Cesium.HeadingPitchRange(0, -Math.PI / 8, 2900)
);
// Orbit around this point.
viewer.clock.onTick.addEventListener(function (clock) {
viewer.scene.camera.rotateRight(0.005);
});
Untuk informasi selengkapnya tentang cara mengontrol kamera, lihat Mengontrol kamera
Menggunakan Cesium untuk Unreal
Untuk menggunakan Plugin Cesium for Unreal dengan 3D Tiles API, ikuti langkah-langkah di bawah ini.
Instal plugin Cesium for Unreal.
Buat project Unreal baru.
Menghubungkan ke Google Photorealistic 3D Tiles API.
Buka jendela Cesium dengan memilih Cesium > Cesium dari menu.
Pilih Set Kartu Kartu Kartu 3D Kosong.
Di World Outliner, buka panel Details dengan memilih Cesium3DTileset ini.
Ubah Sumber dari Dari Cesium Ion menjadi Dari URL.
Tetapkan URL sebagai URL Kartu 3D Google.
https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY
- Aktifkan Tampilkan Kredit di Layar untuk menampilkan atribusi dengan benar.
Tindakan ini akan memuat dunia. Untuk berpindah ke LatLng mana pun, pilih item CesiumGeoreference di panel Outliner, lalu edit Origin Latitude/Longitude/Height di panel Details.
Menggunakan Cesium untuk Unity
Untuk menggunakan ubin fotorealistik dengan Cesium untuk Unity, ikuti langkah-langkah di bawah.
Buat project Unity baru.
Tambahkan Scoped Registry baru di bagian Package Manager (melalui Editor > Project Settings).
Nama: Cesium
URL: https://unity.pkg.cesium.com
Cakupan: com.cesium.unity
Instal paket Cesium untuk Unity.
Menghubungkan ke Google Photorealistic 3D Tiles API.
Buka jendela Cesium dengan memilih Cesium > Cesium dari menu.
Klik Set Kartu Kartu Kartu 3D Kosong.
Di panel sebelah kiri, pada opsi Sumber Kartu di bagian Sumber, pilih Dari URL (bukan Dari Cesium Ion).
Tetapkan URL ke URL Kartu 3D Google.
https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY
- Aktifkan Tampilkan Kredit di Layar untuk menampilkan atribusi dengan benar.
Tindakan ini akan memuat dunia. Untuk berpindah ke LatLng mana pun, pilih item CesiumGeoreference di Scene Hierarchy, lalu edit Origin Latitude/Longitude/Height di Inspector.
Menggunakan deck.gl
deck.gl, yang didukung oleh WebGL, adalah framework JavaScript open source untuk visualisasi data berskala besar dan berperforma tinggi.
Atribusi
Pastikan Anda menampilkan atribusi data dengan benar dengan mengekstrak kolom copyright
dari ubin gltf asset
, lalu menampilkannya di tampilan yang dirender. Untuk mengetahui informasi selengkapnya, lihat Menampilkan atribusi data.
Contoh perender deck.gl
Contoh sederhana
Contoh berikut melakukan inisialisasi perender deck.gl, lalu memuat tempat dalam 3D. Dalam kode Anda, pastikan untuk mengganti YOUR_API_KEY dengan kunci API Anda yang sebenarnya.
<!DOCTYPE html>
<html>
<head>
<title>deck.gl Photorealistic 3D Tiles example</title>
<script src="https://unpkg.com/deck.gl@latest/dist.min.js"></script>
<style>
body { margin: 0; padding: 0;}
#map { position: absolute; top: 0;bottom: 0;width: 100%;}
#credits { position: absolute; bottom: 0; right: 0; padding: 2px; font-size: 15px; color: white;
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;}
</style>
</head>
<body>
<div id="map"></div>
<div id="credits"></div>
<script>
const GOOGLE_API_KEY = YOUR_API_KEY;
const TILESET_URL = `https://tile.googleapis.com/v1/3dtiles/root.json`;
const creditsElement = document.getElementById('credits');
new deck.DeckGL({
container: 'map',
initialViewState: {
latitude: 50.0890,
longitude: 14.4196,
zoom: 16,
bearing: 90,
pitch: 60,
height: 200
},
controller: {minZoom: 8},
layers: [
new deck.Tile3DLayer({
id: 'google-3d-tiles',
data: TILESET_URL,
loadOptions: {
fetch: {
headers: {
'X-GOOG-API-KEY': GOOGLE_API_KEY
}
}
},
onTilesetLoad: tileset3d => {
tileset3d.options.onTraversalComplete = selectedTiles => {
const credits = new Set();
selectedTiles.forEach(tile => {
const {copyright} = tile.content.gltf.asset;
copyright.split(';').forEach(credits.add, credits);
creditsElement.innerHTML = [...credits].join('; ');
});
return selectedTiles;
}
}
})
]
});
</script>
</body>
</html>
Memvisualisasikan lapisan 2D di atas Petak 3D Fotorealistik Google
TerrainExtension deck.gl merender data 2D ke permukaan 3D. Misalnya, Anda dapat menempatkan GeoJSON jejak bangunan di atas Geometri Kartu 3D Fotorealistik.
Pada contoh berikut, lapisan bangunan divisualisasi dengan poligon yang disesuaikan dengan platform 3D Photorealistic Tiles.
<!DOCTYPE html>
<html>
<head>
<title>Google 3D tiles example</title>
<script src="https://unpkg.com/deck.gl@latest/dist.min.js"></script>
<style>
body { margin: 0; padding: 0;}
#map { position: absolute; top: 0;bottom: 0;width: 100%;}
#credits { position: absolute; bottom: 0; right: 0; padding: 2px; font-size: 15px; color: white;
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;}
</style>
</head>
<body>
<div id="map"></div>
<div id="credits"></div>
<script>
const GOOGLE_API_KEY = YOUR_API_KEY;
const TILESET_URL = `https://tile.googleapis.com/v1/3dtiles/root.json`;
const BUILDINGS_URL = 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/google-3d-tiles/buildings.geojson'
const creditsElement = document.getElementById('credits');
const deckgl = new deck.DeckGL({
container: 'map',
initialViewState: {
latitude: 50.0890,
longitude: 14.4196,
zoom: 16,
bearing: 90,
pitch: 60,
height: 200
},
controller: true,
layers: [
new deck.Tile3DLayer({
id: 'google-3d-tiles',
data: TILESET_URL,
loadOptions: {
fetch: {
headers: {
'X-GOOG-API-KEY': GOOGLE_API_KEY
}
}
},
onTilesetLoad: tileset3d => {
tileset3d.options.onTraversalComplete = selectedTiles => {
const credits = new Set();
selectedTiles.forEach(tile => {
const {copyright} = tile.content.gltf.asset;
copyright.split(';').forEach(credits.add, credits);
creditsElement.innerHTML = [...credits].join('; ');
});
return selectedTiles;
}
},
operation: 'terrain+draw'
}),
new deck.GeoJsonLayer({
id: 'buildings',
// This dataset is created by CARTO, using other Open Datasets available. More info at: https://3dtiles.carto.com/#about.
data: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/google-3d-tiles/buildings.geojson',
stroked: false,
filled: true,
getFillColor: ({properties}) => {
const {tpp} = properties;
// quantiles break
if (tpp < 0.6249)
return [254, 246, 181]
else if (tpp < 0.6780)
return [255, 194, 133]
else if (tpp < 0.8594)
return [250, 138, 118]
return [225, 83, 131]
},
opacity: 0.2,
extensions: [new deck._TerrainExtension()]
})
]
});
</script>
</body>
</html>