3D Karo Oluşturucu ile çalışma

Fotogerçekçi 3D Karolar, OGC standart glTF biçimindedir. Yani 3D görselleştirmelerinizi oluşturmak için OGC 3D Karolar spesifikasyonunu destekleyen herhangi bir oluşturucuyu kullanabilirsiniz. Örneğin Sezyum, 3D görselleştirmeler oluşturmak için temel bir açık kaynak kitaplığıdır.

CesiumJS ile çalışma

CesiumJS, web'de 3D görselleştirme için açık kaynak bir JavaScript kitaplığıdır. CesiumJS kullanmayla ilgili daha fazla bilgi için Learn CesiumJS bölümüne bakın.

Kullanıcı denetimleri

CesiumJS karo oluşturucuda standart bir kullanıcı denetimi grubu bulunur.

İşlem Açıklama
Kaydırma görünümü Sol tıklama ve sürükleme
Görünümü yakınlaştır Sağ tıklayın ve sürükleyin veya fare tekerleğini kaydırın
Görünümü döndür Ctrl + sol/sağ tıklama ve sürükleme veya orta tıklayıp sürükleme

En iyi uygulamalar

CesiumJS 3D yükleme sürelerini azaltmak için uygulayabileceğiniz birkaç yaklaşım vardır. Örneğin:

  • Oluşturma HTML'nize aşağıdaki ifadeyi ekleyerek eşzamanlı istekleri etkinleştirin:

    Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = <REQUEST_COUNT>
    

    REQUEST_COUNT değeri ne kadar yüksek olursa karolar o kadar hızlı yüklenir. Ancak, REQUEST_COUNT 10'dan yüksek ve önbellek devre dışı olan bir Chrome tarayıcıya yükleme yaparken bilinen bir Chrome sorunuyla karşılaşabilirsiniz. Çoğu kullanım alanında optimum performans için 18 üzerinden REQUEST_COUNT öneririz.

  • Ayrıntı düzeylerini atlamayı etkinleştir. Daha fazla bilgi için bu Sezyum sorununa göz atın.

showCreditsOnScreen: true özelliğini etkinleştirerek veri ilişkilendirmelerini düzgün gösterdiğinizden emin olun. Daha fazla bilgi için Politikalar bölümüne bakın.

Oluşturma metrikleri

Kare hızını bulmak için requestAnimationFrame yönteminin saniyede kaç kez çağrıldığına bakın.

Kare gecikmesinin nasıl hesaplandığını görmek için PerformanceDisplay sınıfına göz atın.

CesiumJS oluşturucu örnekleri

Kök parça kümesi URL'sini sağlayarak CesiumJS oluşturucuyu Map Tiles API'nin 3D Karoları ile kullanabilirsiniz.

Basit örnek

Aşağıdaki örnek, CesiumJS oluşturucuyu başlatır ve ardından kök parça kümesini yükler.

<!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>

requestRenderMode hakkında bilgi edinmek için İstek oluşturma modunu etkinleştirme bölümüne bakın.

HTML sayfası burada gösterildiği gibi oluşturulur.

Places API entegrasyonu

Daha fazla bilgi almak için CesiumJS'yi Places API ile kullanabilirsiniz. Yerler görünümüne gitmek için Otomatik Tamamlama widget'ını kullanabilirsiniz. Bu örnekte, bu talimatlar uygulanarak etkinleştirilen Yerler Otomatik Tamamlama API'si ve bu talimatlar uygulanarak etkinleştirilen Maps JavaScript API kullanılmaktadır.

<!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>

Dönen drone görünümü

Kamerayı parça kümesi üzerinden animasyon uygulanacak şekilde kontrol edebilirsiniz. Bu animasyon, Places API ve Elevation API ile birlikte kullanıldığında herhangi bir önemli noktanın etkileşimli bir drone uçurmasını simüle eder.

Bu kod örneği, Otomatik Tamamlama widget'ında seçtiğiniz yerde gezinmenizi sağlar.

<!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>

Çoklu çizgi ve etiket çizme

Bu kod örneğinde, bir haritaya çoklu çizgi ve etiketin nasıl ekleneceği gösterilmektedir. Arabayla ve yaya yol tarifini göstermek, mülk sınırlarını göstermek veya sürüş ve yürüyüş sürelerini hesaplamak için haritaya çoklu çizgi ekleyebilirsiniz. Özellikleri sahneyi fiilen oluşturmadan da alabilirsiniz.

Kullanıcıları bir semtte özel olarak seçilmiş bir tura yönlendirebilir veya civardaki mülklerde şu anda indirimde olan mülkleri gösterebilir, ardından sahneye ilan tahtaları gibi 3D nesneler ekleyebilirsiniz.

Bir geziyi özetleyerek görüntülediğiniz tesisleri listeleyebilir, bu ayrıntıları sanal nesnelerde görüntüleyebilirsiniz.

<!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>

Kamera yörüngesi

Sesium'da kamerayı bir önemli yerin etrafında döndürerek binalarla çarpışmalardan kaçınabilirsiniz. Alternatif olarak, kamera içlerinde gezerken yapıları şeffaf hale de getirebilirsiniz.

Önce kamerayı bir noktaya kilitleyin, ardından öğenizi sergilemek için bir kamera yörüngesi oluşturabilirsiniz. Bu kod örneğinde gösterildiği gibi, kameranın lookAtTransform işlevini bir etkinlik işleyici ile kullanarak bunu yapabilirsiniz.

// 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);
});

Kamerayı denetleme hakkında daha fazla bilgi için bkz. Kamerayı kontrol etme

Cesium for Unreal ile Çalışın

Cesium for Unreal Eklentisi'ni 3D Tiles API ile kullanmak için aşağıdaki adımları uygulayın.

  1. Cesium for Unreal eklentisini yükleyin.

  2. Yeni bir Unreal projesi oluşturun.

  3. Google Fotogerçekçi 3D Karolar API'sine bağlanın.

    1. Menüden Sezyum > Sezyum'u seçerek Sezyum penceresini açın.

    2. Boş 3D Karo Grubu'nu seçin.

    3. World Outliner'da bu Cesium3DTileset öğesini seçerek Ayrıntılar panelini açın.

    4. Source'u (Kaynak), From Cesium Ion'dan (Cesium Ion'dan) From URL'ye (URL'den) değiştirin.

    5. URL'yi Google 3D Karo URL'si olacak şekilde ayarlayın.

    https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY
    
    1. İlişkilendirmeleri düzgün bir şekilde görüntülemek için Kredileri Ekranda Göster seçeneğini etkinleştirin.
  4. Bu, tüm dünyayı yüklüyor. Herhangi bir LatLng'e gitmek için Anahat panelinde CesiumGeoreference öğesini seçin ve ardından Ayrıntılar panelinde Kaynak Enlem/Boylam/Yükseklik değerini düzenleyin.

Unity için Cesium ile çalışma

Unity için Sesium ile fotogerçekçi kutular kullanmak istiyorsanız aşağıdaki adımları uygulayın.

  1. Yeni bir Unity projesi oluşturun.

  2. Paket Yöneticisi bölümünde (Düzenleyici > Proje Ayarları üzerinden) yeni bir Kapsamlı Kayıt Defteri ekleyin.

    • Ad: Sezyum

    • URL: https://unity.pkg.cesium.com

    • Kapsamlar: com.cesium.unity

  3. Unity için Cesium paketini yükleyin.

  4. Google Fotogerçekçi 3D Karolar API'sine bağlanın.

    1. Menüden Sezyum > Sezyum'u seçerek Sezyum penceresini açın.

    2. Boş 3D Karo Grubu'nu tıklayın.

    3. Sol panelde, Source'un (Kaynak) altındaki Tileset Source (Dişli Set Kaynağı) seçeneğinde From URL (URL'den) seçeneğini (Cesyum Ion'dan değil) seçin.

    4. URL'yi, Google 3D Karolar URL'sine ayarlayın.

    https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY
    
    1. İlişkilendirmeleri düzgün bir şekilde görüntülemek için Kredileri Ekranda Göster seçeneğini etkinleştirin.
  5. Bu, tüm dünyayı yüklüyor. Herhangi bir EnlBoy'a gitmek için Sahne Hiyerarşisi'nde CesiumGeoreference öğesini seçin ve ardından İnceleyici'de Kaynak Enlem/Boylam/Yükseklik değerini düzenleyin.

Dec.gl ile çalışma

WebGL tarafından desteklenen deck.gl yüksek performanslı ve büyük ölçekli veri görselleştirmeleri için açık kaynaklı bir JavaScript çerçevesidir.

İlişkilendirme

asset parçalarından copyright alanını çıkarıp oluşturulan görünümde göstererek veri ilişkilendirmelerini düzgün bir şekilde görüntülediğinizden emin olun. Daha fazla bilgi için Görüntülü reklam ağı veri ilişkilendirmeleri bölümüne bakın.

deste.gl oluşturucu örnekleri

Basit örnek

Aşağıdaki örnekte, Deck.gl oluşturucusu başlatılır ve ardından 3D olarak bir yer yüklenir. Kodunuzda, YOUR_API_KEY yerine gerçek API anahtarınızı yazdığınızdan emin olun.

<!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>

Google Fotogerçekçi 3D Karolar'ın üzerinde 2D katmanları görselleştirin

Decs.gl TerrainExtension, aksi takdirde 2D verilerini 3D yüzeye oluşturur. Örneğin, bir binanın kapladığı yerin GeoJSON'unu Fotogerçekçi 3D Karo Geometrisi üzerine yerleştirebilirsiniz.

Aşağıdaki örnekte, bir bina katmanı Fotogerçekçi 3D Karolar yüzeyine uyarlanmış poligonlarla görselleştirilmiştir.

<!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>