diff --git a/.env.example b/.env.example index 9ef91ad..287a2cb 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,3 @@ # Ref: https://github.com/CesiumGS/cesium/blob/main/packages/engine/Source/Core/Ion.js#L7 -EXAMPLE_CESIUM_ION_ACCESS_TOKEN=your_access_token_here \ No newline at end of file +EXAMPLE_CESIUM_ION_ACCESS_TOKEN=your_access_token_here +EXAMPLE_GOOGLE_MAP_API_KEY=your_google_map_api_key diff --git a/example/testLayers/google_photorealistic_3dtiles.ts b/example/testLayers/google_photorealistic_3dtiles.ts new file mode 100644 index 0000000..77590d1 --- /dev/null +++ b/example/testLayers/google_photorealistic_3dtiles.ts @@ -0,0 +1,13 @@ +import { Layer } from "@reearth/core"; + +export const GOOGLE_PHOTOREALISTIC_3DTILES: Layer = { + id: "google_photorealistic_3dtiles", + type: "simple", + data: { + type: "google-photorealistic", + serviceTokens: { + googleMapApiKey: import.meta.env.EXAMPLE_GOOGLE_MAP_API_KEY || "", + }, + }, + "3dtiles": {}, +}; diff --git a/example/testLayers/index.ts b/example/testLayers/index.ts index 8124456..628def5 100644 --- a/example/testLayers/index.ts +++ b/example/testLayers/index.ts @@ -2,6 +2,16 @@ import { Layer } from "@reearth/core"; import { GEOJSON_MARKER } from "./geojson_marker"; import { GEOJSON_SIMPLE } from "./geojson_simple"; +import { GOOGLE_PHOTOREALISTIC_3DTILES } from "./google_photorealistic_3dtiles"; import { LAND_USE } from "./mvt"; +import { OSM_BUILDINGS } from "./osm_buildings"; +import { THREEDTILES_SIMPLE } from "./threedtiles_simple"; -export const TEST_LAYERS: Layer[] = [LAND_USE, GEOJSON_MARKER, GEOJSON_SIMPLE]; +export const TEST_LAYERS: Layer[] = [ + LAND_USE, + GEOJSON_MARKER, + GEOJSON_SIMPLE, + GOOGLE_PHOTOREALISTIC_3DTILES, + OSM_BUILDINGS, + THREEDTILES_SIMPLE, +]; diff --git a/example/testLayers/osm_buildings.ts b/example/testLayers/osm_buildings.ts new file mode 100644 index 0000000..41a0fac --- /dev/null +++ b/example/testLayers/osm_buildings.ts @@ -0,0 +1,10 @@ +import { Layer } from "@reearth/core"; + +export const OSM_BUILDINGS: Layer = { + id: "osm_buildings", + type: "simple", + data: { + type: "osm-buildings", + }, + "3dtiles": {}, +}; diff --git a/example/testLayers/threedtiles_simple.ts b/example/testLayers/threedtiles_simple.ts new file mode 100644 index 0000000..0fa26fe --- /dev/null +++ b/example/testLayers/threedtiles_simple.ts @@ -0,0 +1,11 @@ +import { Layer } from "@reearth/core"; + +export const THREEDTILES_SIMPLE: Layer = { + id: "3dtiles_simple", + type: "simple", + data: { + type: "3dtiles", + url: "https://assets.cms.plateau.reearth.io/assets/4f/702958-5009-4d6b-a2e0-157c7e573eb2/13100_tokyo23-ku_2022_3dtiles _1_1_op_bldg_13101_chiyoda-ku_lod2_no_texture/tileset.json", + }, + "3dtiles": {}, +}; diff --git a/src/engines/Cesium/Feature/Tileset/hooks.ts b/src/engines/Cesium/Feature/Tileset/hooks.ts index affbf45..d2fd160 100644 --- a/src/engines/Cesium/Feature/Tileset/hooks.ts +++ b/src/engines/Cesium/Feature/Tileset/hooks.ts @@ -15,13 +15,11 @@ import { Cesium3DTileFeature, Model, Cesium3DTilePointFeature, - GoogleMaps as CesiumGoogleMaps, - Resource, - defaultValue, ImageBasedLighting, Cesium3DTileContent, Color, Viewer, + createGooglePhotorealistic3DTileset, } from "cesium"; import { pick } from "lodash-es"; import { MutableRefObject, useCallback, useEffect, useMemo, useRef, useState } from "react"; @@ -57,7 +55,6 @@ import { } from "../utils"; import { TilesetFeatureIndex } from "./TilesetFeatureIndex"; -import { GoogleMaps } from "./types"; import { useClippingBox } from "./useClippingBox"; import { useDrawClipping } from "./useDrawClipping"; @@ -77,6 +74,7 @@ const useData = (layer: ComputedLayer | undefined) => { ? data.layers.join(",") : data?.layers : undefined, + googleMapApiKey: data?.serviceTokens?.googleMapApiKey, }; }, [layer]); }; @@ -460,7 +458,6 @@ export const useHooks = ({ edgeColor, edgeWidth, experimental_clipping, - apiKey, selectedFeatureColor, disableIndexingFeature, } = property ?? {}; @@ -481,7 +478,7 @@ export const useHooks = ({ } = useClippingBox({ clipping: experimental_clipping, boxId }); const [style, setStyle] = useState(); - const { url, type, idProperty } = useData(layer); + const { url, type, idProperty, googleMapApiKey } = useData(layer); const shouldUseFeatureIndex = !disableIndexingFeature && !!idProperty; const [isTilesetReady, setIsTilesetReady] = useState(false); @@ -708,31 +705,33 @@ export const useHooks = ({ })(); }, [styleUrl]); - const googleMapResource = useMemo(() => { - if (type !== "google-photorealistic" || !isVisible) return; - // Ref: https://github.com/CesiumGS/cesium/blob/b208135a095073386e5f04a59956ee11a03aa847/packages/engine/Source/Scene/createGooglePhotorealistic3DTileset.js#L30 - const googleMaps = CesiumGoogleMaps as GoogleMaps; - // Default key: https://github.com/CesiumGS/cesium/blob/b208135a095073386e5f04a59956ee11a03aa847/packages/engine/Source/Core/GoogleMaps.js#L6C36-L6C36 - const key = defaultValue(apiKey, googleMaps.defaultApiKey); - const credit = googleMaps.getDefaultApiKeyCredit(key); - return new Resource({ - url: `${googleMaps.mapTilesApiEndpoint}3dtiles/root.json`, - queryParameters: { key }, - credits: credit ? [credit] : undefined, - } as Resource.ConstructorOptions); - }, [apiKey, type, isVisible]); + const googleMapPhotorealisticResource = useMemo(() => { + if (type !== "google-photorealistic" || !isVisible) return null; + + const loadTileset = async () => { + try { + const tileset = await createGooglePhotorealistic3DTileset(googleMapApiKey); + return tileset.resource; + } catch (error) { + console.error(`Error loading Photorealistic 3D Tiles tileset: ${error}`); + throw error; + } + }; + + return loadTileset(); + }, [type, isVisible, googleMapApiKey]); const tilesetUrl = useMemo(() => { return type === "osm-buildings" && isVisible ? IonResource.fromAssetId(96188, { accessToken: meta?.cesiumIonAccessToken as string | undefined, }) // https://github.com/CesiumGS/cesium/blob/main/packages/engine/Source/Scene/createOsmBuildings.js#L53 - : googleMapResource - ? googleMapResource + : googleMapPhotorealisticResource && isVisible + ? googleMapPhotorealisticResource : type === "3dtiles" && isVisible ? url ?? tileset : null; - }, [isVisible, tileset, url, type, meta, googleMapResource]); + }, [type, isVisible, meta?.cesiumIonAccessToken, googleMapPhotorealisticResource, url, tileset]); const imageBasedLighting = useMemo(() => { if ( diff --git a/src/mantle/types/appearance.ts b/src/mantle/types/appearance.ts index 981f3b0..5377dd4 100644 --- a/src/mantle/types/appearance.ts +++ b/src/mantle/types/appearance.ts @@ -200,7 +200,6 @@ export type Cesium3DTilesAppearance = { selectedFeatureColor?: string; // This doesn't support expression disableIndexingFeature?: boolean; tileset?: string; - apiKey?: string; experimental_clipping?: EXPERIMENTAL_clipping; pointSize?: number; meta?: unknown; diff --git a/src/mantle/types/index.ts b/src/mantle/types/index.ts index 2de184a..013ad70 100644 --- a/src/mantle/types/index.ts +++ b/src/mantle/types/index.ts @@ -76,6 +76,9 @@ export type Data = { updateInterval?: number; // milliseconds parameters?: Record; idProperty?: string; + serviceTokens?: { + googleMapApiKey?: string; + }; time?: { property?: string; interval?: number; // milliseconds