Skip to content

Commit

Permalink
feat(web): update cesium (#951)
Browse files Browse the repository at this point in the history
  • Loading branch information
keiya01 authored Apr 9, 2024
1 parent 232a446 commit b77f586
Show file tree
Hide file tree
Showing 24 changed files with 336 additions and 220 deletions.
6 changes: 3 additions & 3 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
"array-move": "4.0.0",
"aws-amplify": "5.3.11",
"axios": "1.6.0",
"cesium": "1.105.2",
"cesium": "1.116.0",
"cesium-dnd": "1.1.0",
"cesium-mvt-imagery-provider": "1.4.0",
"core-js": "3.33.2",
Expand Down Expand Up @@ -188,7 +188,7 @@
"react-use": "17.4.0",
"react18-json-view": "0.2.7",
"remark-gfm": "3.0.1",
"resium": "1.16.1",
"resium": "1.17.3",
"suspend-react": "^0.1.3",
"tinycolor2": "1.6.0",
"ts-easing": "0.2.0",
Expand All @@ -198,4 +198,4 @@
"uuid": "9.0.1",
"xstate": "4.38.2"
}
}
}
25 changes: 13 additions & 12 deletions web/src/beta/lib/core/engines/Cesium/Feature/Tileset/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ const useFeature = ({
evalFeature,
onComputedFeatureFetch,
shouldUseFeatureIndex,
isTilesetReady,
}: {
id?: string;
tileset: MutableRefObject<Cesium3DTileset | undefined>;
Expand All @@ -200,6 +201,7 @@ const useFeature = ({
featureIndex: TilesetFeatureIndex;
selectedFeatureIdsRef: MutableRefObject<string[]>;
shouldUseFeatureIndex?: boolean;
isTilesetReady: boolean;
}) => {
const cachedFeaturesRef = useRef<CachedFeature[]>([]);
const cachedCalculatedLayerRef = useRef(layer);
Expand Down Expand Up @@ -326,7 +328,7 @@ const useFeature = ({
tileset.current?.tileLoad.addEventListener((t: Cesium3DTile) =>
handleTilesetLoadRef.current(t),
),
[tileset],
[tileset, isTilesetReady],
);

const handleTilesetUnload = useCallback(
Expand All @@ -345,7 +347,7 @@ const useFeature = ({
tileset.current?.tileUnload.addEventListener((t: Cesium3DTile) =>
handleTilesetUnloadRef.current(t),
),
[tileset],
[tileset, isTilesetReady],
);

useEffect(() => {
Expand Down Expand Up @@ -483,6 +485,8 @@ export const useHooks = ({
const { url, type, idProperty } = useData(layer);
const shouldUseFeatureIndex = !disableIndexingFeature && !!idProperty;

const [isTilesetReady, setIsTilesetReady] = useState(false);

const prevPlanes = useRef(_planes);
const planes = useMemo(() => {
if (
Expand Down Expand Up @@ -522,6 +526,7 @@ export const useHooks = ({
tilesetRef,
viewer,
clippingPlanes,
isTilesetReady,
});
const [featureIndex] = useState(() => new TilesetFeatureIndex());

Expand All @@ -548,7 +553,7 @@ export const useHooks = ({
const [selectedFeatureColorMap] = useState(() => new Map<string, Color>());

useEffect(() => {
if (!tilesetRef.current || !shouldUseFeatureIndex) return;
if (!tilesetRef.current || !shouldUseFeatureIndex || !isTilesetReady) return;
Object.assign(tilesetRef.current, {
onSelectFeature: (f: Cesium3DTileFeature) => {
const tag = getTag(f);
Expand All @@ -570,7 +575,7 @@ export const useHooks = ({
f.color = selectedFeatureColorMap.get(tag?.featureId ?? "") ?? DEFAULT_FEATURE_COLOR;
},
});
}, [selectedFeatureColorMap, featureIndex, shouldUseFeatureIndex]);
}, [selectedFeatureColorMap, featureIndex, shouldUseFeatureIndex, isTilesetReady]);

useFeature({
id,
Expand All @@ -583,6 +588,7 @@ export const useHooks = ({
featureIndex,
selectedFeatureIdsRef,
shouldUseFeatureIndex,
isTilesetReady,
});

const [terrainHeightEstimate, setTerrainHeightEstimate] = useState(0);
Expand Down Expand Up @@ -615,14 +621,7 @@ export const useHooks = ({
const position = Cartesian3.fromDegrees(coords?.[0] || 0, coords?.[1] || 0, coords?.[2] || 0);

const prepareClippingPlanes = async () => {
if (!tilesetRef.current) {
return;
}

try {
await tilesetRef.current?.readyPromise;
} catch (e) {
console.error("Could not load 3D tiles: ", e);
if (!tilesetRef.current || !isTilesetReady) {
return;
}

Expand Down Expand Up @@ -672,6 +671,7 @@ export const useHooks = ({
allowEnterGround,
terrainHeightEstimate,
experimental_clipping?.draw,
isTilesetReady,
]);

useEffect(() => {
Expand Down Expand Up @@ -773,6 +773,7 @@ export const useHooks = ({

const handleReady = useCallback(
(tileset: Cesium3DTileset) => {
setIsTilesetReady(true);
onLayerFetch?.({ properties: tileset.properties });
onLayerLoad?.({ layerId: layerIdRef.current });
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { MutableRefObject, useEffect, useMemo, useState } from "react";

import { LatLng } from "../../..";
import { sampleTerrainHeight } from "../../common";
import { useContext } from "../context";

import { ClippingPolygonStyle } from "./DrawClippingPolygon";

Expand All @@ -29,6 +30,7 @@ type drawClippingProps = {
tilesetRef?: MutableRefObject<Cesium3DTileset | undefined>;
viewer?: Viewer;
clippingPlanes: ClippingPlaneCollection;
isTilesetReady: boolean;
};

export const useDrawClipping = ({
Expand All @@ -42,26 +44,22 @@ export const useDrawClipping = ({
tilesetRef,
viewer,
clippingPlanes,
isTilesetReady,
}: drawClippingProps) => {
const [baseHeight, setBaseHeight] = useState(0);
const appliedTop = useMemo(() => top ?? 100, [top]);
const appliedBottom = useMemo(() => bottom ?? 10, [bottom]);
const [ready, setReady] = useState(false);
const { requestRender } = useContext();

useEffect(() => {
const updateClippingPlanes = async () => {
if (!tilesetRef?.current) return;

try {
await tilesetRef.current.readyPromise;
} catch (e) {
console.error("Could not load 3D tiles: ", e);
return;
}
if (!tilesetRef?.current || !isTilesetReady) return;

if (!enabled || !surfacePoints || surfacePoints?.length < 2) {
clippingPlanes.removeAll();
setBaseHeight(0);
requestRender?.();
return;
}

Expand Down Expand Up @@ -135,6 +133,8 @@ export const useDrawClipping = ({
enabled,
direction,
viewer,
isTilesetReady,
requestRender,
]);

useEffect(() => {
Expand Down
14 changes: 13 additions & 1 deletion web/src/beta/lib/core/engines/Cesium/Feature/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import LRUCache from "lru-cache";
import { useMemo } from "react";
import { useEffect, useMemo } from "react";

import { ComputedFeature, DataType, guessType } from "@reearth/beta/lib/core/mantle";

import type { AppearanceTypes, FeatureComponentProps, ComputedLayer } from "../..";

import Box, { config as boxConfig } from "./Box";
import { useContext } from "./context";
import Ellipse, { config as ellipseConfig } from "./Ellipse";
import Ellipsoid, { config as ellipsoidConfig } from "./Ellipsoid";
import Frustum, { config as frustumConfig } from "./Frustum";
Expand Down Expand Up @@ -112,6 +113,17 @@ export default function Feature({
const cacheable = !data?.updateInterval && !useTransition;
const urlMD5 = useMemo(() => (data?.url ? generateIDWithMD5(data.url) : ""), [data?.url]);

const { requestRender } = useContext();
// TODO: Find a way to wait updating the entity
useEffect(() => {
setTimeout(() => {
requestRender?.();
}, 300);
});

// Need to invoke requestRender when it's unmounted
useEffect(() => () => requestRender?.(), [requestRender]);

const renderComponent = (k: keyof AppearanceTypes, f?: ComputedFeature): JSX.Element | null => {
if (!isRenderableAppearance(k)) return null;

Expand Down
38 changes: 19 additions & 19 deletions web/src/beta/lib/core/engines/Cesium/core/Globe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default function Globe({ property, cesiumIonAccessToken }: Props): JSX.El
[property?.terrain, property?.default],
);

const terrainProvider = useMemo((): TerrainProvider | undefined => {
const terrainProvider = useMemo((): Promise<TerrainProvider> | TerrainProvider | undefined => {
const opts = {
terrain: terrainProperty?.terrain,
terrainType: terrainProperty?.terrainType,
Expand Down Expand Up @@ -72,8 +72,6 @@ export default function Globe({ property, cesiumIonAccessToken }: Props): JSX.El
atmosphereBrightnessShift={property?.atmosphere?.brightness_shift}
terrainProvider={terrainProvider}
depthTestAgainstTerrain={!!terrainProperty.depthTestAgainstTerrain}
terrainExaggerationRelativeHeight={terrainProperty.terrainExaggerationRelativeHeight}
terrainExaggeration={terrainProperty.terrainExaggeration}
/>
);
}
Expand Down Expand Up @@ -103,35 +101,37 @@ const terrainProviders: {
| "terrainCesiumIonUrl"
| "terrainNormal"
>,
) => TerrainProvider | null);
) => Promise<TerrainProvider> | TerrainProvider | null);
} = {
cesium: ({ terrainCesiumIonAccessToken, terrainNormal }) =>
new CesiumTerrainProvider({
url: IonResource.fromAssetId(1, {
CesiumTerrainProvider.fromUrl(
IonResource.fromAssetId(1, {
accessToken: terrainCesiumIonAccessToken,
}),
requestVertexNormals: terrainNormal,
requestWaterMask: false,
}),
arcgis: ({ terrainNormal }) =>
new ArcGISTiledElevationTerrainProvider({
url: "https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer",
requestVertexNormals: terrainNormal,
}),
{
requestVertexNormals: terrainNormal,
requestWaterMask: false,
},
),
arcgis: () =>
ArcGISTiledElevationTerrainProvider.fromUrl(
"https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer",
),
cesiumion: ({
terrainCesiumIonAccessToken,
terrainCesiumIonAsset,
terrainCesiumIonUrl,
terrainNormal,
}) =>
terrainCesiumIonAsset
? new CesiumTerrainProvider({
url:
terrainCesiumIonUrl ||
? CesiumTerrainProvider.fromUrl(
terrainCesiumIonUrl ||
IonResource.fromAssetId(parseInt(terrainCesiumIonAsset, 10), {
accessToken: terrainCesiumIonAccessToken,
}),
requestVertexNormals: terrainNormal,
})
{
requestVertexNormals: terrainNormal,
},
)
: null,
};
25 changes: 18 additions & 7 deletions web/src/beta/lib/core/engines/Cesium/core/Imagery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
TextureMinificationFilter,
} from "cesium";
import { isEqual } from "lodash-es";
import { useCallback, useMemo, useRef, useLayoutEffect } from "react";
import { useCallback, useMemo, useRef, useLayoutEffect, useState } from "react";
import { ImageryLayer } from "resium";

import { tiles as tilePresets } from "./presets";
Expand Down Expand Up @@ -42,19 +42,23 @@ export default function ImageryLayers({ tiles, cesiumIonAccessToken }: Props) {

// force rerendering all layers when any provider is updated
// since Resium does not sort layers according to ImageryLayer component order
const counter = useRef(0);
const [counter, setCounter] = useState(0);
useLayoutEffect(() => {
if (updated) counter.current++;
if (updated) setCounter(c => c + 1);
}, [providers, updated]);

return (
<>
{tiles
?.map(({ id, ...tile }) => ({ ...tile, id, provider: providers[id]?.[2] }))
?.map(({ id, ...tile }) => ({
...tile,
id,
provider: providers[id]?.[2],
}))
.map(({ id, tile_opacity: opacity, tile_zoomLevel, provider, heatmap }, i) =>
provider ? (
<ImageryLayer
key={`${id}_${i}_${counter.current}`}
key={`${id}_${i}_${counter}`}
imageryProvider={provider}
minimumTerrainLevel={tile_zoomLevel?.[0]}
maximumTerrainLevel={tile_zoomLevel?.[1]}
Expand Down Expand Up @@ -86,7 +90,7 @@ export function useImageryProviders({
cesiumIonAccessToken?: string;
heatmap?: boolean;
tile_zoomLevel?: number[];
}) => ImageryProvider | null;
}) => Promise<ImageryProvider> | ImageryProvider | null;
};
}): { providers: Providers; updated: boolean } {
const newTile = useCallback(
Expand Down Expand Up @@ -134,7 +138,14 @@ export function useImageryProviders({
prevProvider,
tile,
}):
| [string, [string | undefined, string | undefined, ImageryProvider | null | undefined]]
| [
string,
[
string | undefined,
string | undefined,
Promise<ImageryProvider> | ImageryProvider | null | undefined,
],
]
| null =>
!tile
? null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ export const JapanGSIOptimalBVmapLabelImagery: FC<JapanGSIOptimalBVmapLabelImage
disableDepthTestDistance: Infinity,
...styleOptions,
};
return [feature, labelCollection.add(options)];
return [feature, labelCollection.add(options as Label)];
})
.filter(isNotNullish);

Expand Down
Loading

0 comments on commit b77f586

Please sign in to comment.