Skip to content
This repository has been archived by the owner on Apr 25, 2023. It is now read-only.

Commit

Permalink
feat: support Cesium Ion terrain (#331)
Browse files Browse the repository at this point in the history
* custom-terrain-url

* update

* Bug fix

* Revert "Bug fix"

This reverts commit 7b773b4.

* fix: remove get-pixels dependency and used CanvasAPI for PNG conversion to multidimensional array

* remove comments and logging statements

* update

* fix

* remove get-pixels

* relocated the formatting helper statements

* fix

* remove gsi terrain

* refactor

Co-authored-by: nina992 <nouralali992@gmail.com>
Co-authored-by: rot1024 <aayhrot@gmail.com>
Co-authored-by: Piyush Chauhan <piyushchauhan1004@gmail.com>
  • Loading branch information
4 people committed Dec 2, 2022
1 parent bd9dc50 commit e0b99a6
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 91 deletions.
113 changes: 113 additions & 0 deletions src/components/molecules/Visualizer/Engine/Cesium/core/Globe.tsx
@@ -0,0 +1,113 @@
import {
ArcGISTiledElevationTerrainProvider,
CesiumTerrainProvider,
EllipsoidTerrainProvider,
IonResource,
TerrainProvider,
} from "cesium";
import { pick } from "lodash-es";
import { useMemo } from "react";
import { Globe as CesiumGlobe } from "resium";

import { objKeys } from "@reearth/util/util";

import type { SceneProperty, TerrainProperty } from "../../ref";

export type Props = {
property?: SceneProperty;
cesiumIonAccessToken?: string;
};

export default function Globe({ property, cesiumIonAccessToken }: Props): JSX.Element | null {
const terrainProperty = useMemo(
(): TerrainProperty => ({
...property?.terrain,
...pick(property?.default, terrainPropertyKeys),
}),
[property?.terrain, property?.default],
);

const terrainProvider = useMemo((): TerrainProvider | undefined => {
const opts = {
terrain: terrainProperty?.terrain,
terrainType: terrainProperty?.terrainType,
terrainCesiumIonAccessToken:
terrainProperty?.terrainCesiumIonAccessToken || cesiumIonAccessToken,
terrainCesiumIonAsset: terrainProperty?.terrainCesiumIonAsset,
terrainCesiumIonUrl: terrainProperty?.terrainCesiumIonUrl,
};
const provider = opts.terrain ? terrainProviders[opts.terrainType || "cesium"] : undefined;
return (typeof provider === "function" ? provider(opts) : provider) ?? defaultTerrainProvider;
}, [
terrainProperty?.terrain,
terrainProperty?.terrainType,
terrainProperty?.terrainCesiumIonAccessToken,
terrainProperty?.terrainCesiumIonAsset,
terrainProperty?.terrainCesiumIonUrl,
cesiumIonAccessToken,
]);

return (
<CesiumGlobe
enableLighting={!!property?.atmosphere?.enable_lighting}
showGroundAtmosphere={property?.atmosphere?.ground_atmosphere ?? true}
atmosphereSaturationShift={property?.atmosphere?.surturation_shift}
atmosphereHueShift={property?.atmosphere?.hue_shift}
atmosphereBrightnessShift={property?.atmosphere?.brightness_shift}
terrainProvider={terrainProvider}
depthTestAgainstTerrain={!!terrainProperty.depthTestAgainstTerrain}
terrainExaggerationRelativeHeight={terrainProperty.terrainExaggerationRelativeHeight}
terrainExaggeration={terrainProperty.terrainExaggeration}
/>
);
}

const terrainPropertyKeys = objKeys<TerrainProperty>({
terrain: 0,
terrainType: 0,
terrainExaggeration: 0,
terrainExaggerationRelativeHeight: 0,
depthTestAgainstTerrain: 0,
terrainCesiumIonAsset: 0,
terrainCesiumIonAccessToken: 0,
terrainCesiumIonUrl: 0,
terrainUrl: 0,
});

const defaultTerrainProvider = new EllipsoidTerrainProvider();

const terrainProviders: {
[k in NonNullable<TerrainProperty["terrainType"]>]:
| TerrainProvider
| ((
opts: Pick<
TerrainProperty,
"terrainCesiumIonAccessToken" | "terrainCesiumIonAsset" | "terrainCesiumIonUrl"
>,
) => TerrainProvider | null);
} = {
cesium: ({ terrainCesiumIonAccessToken }) =>
// https://github.com/CesiumGS/cesium/blob/main/Source/Core/createWorldTerrain.js
new CesiumTerrainProvider({
url: IonResource.fromAssetId(1, {
accessToken: terrainCesiumIonAccessToken,
}),
requestVertexNormals: false,
requestWaterMask: false,
}),
arcgis: () =>
new ArcGISTiledElevationTerrainProvider({
url: "https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer",
}),
cesiumion: ({ terrainCesiumIonAccessToken, terrainCesiumIonAsset, terrainCesiumIonUrl }) =>
terrainCesiumIonAsset
? new CesiumTerrainProvider({
url:
terrainCesiumIonUrl ||
IonResource.fromAssetId(parseInt(terrainCesiumIonAsset, 10), {
accessToken: terrainCesiumIonAccessToken,
}),
requestVertexNormals: true,
})
: null,
};
42 changes: 1 addition & 41 deletions src/components/molecules/Visualizer/Engine/Cesium/hooks.ts
@@ -1,5 +1,5 @@
import { Color, Entity, Cesium3DTileFeature, Cartesian3, Clock as CesiumClock, Ion } from "cesium";
import type { Viewer as CesiumViewer, TerrainProvider } from "cesium";
import type { Viewer as CesiumViewer } from "cesium";
import CesiumDnD, { Context } from "cesium-dnd";
import { isEqual } from "lodash-es";
import { useCallback, useEffect, useMemo, useRef } from "react";
Expand All @@ -22,7 +22,6 @@ import {
getLocationFromScreen,
getClock,
} from "./common";
import terrain from "./terrain";
import useEngineRef from "./useEngineRef";
import { convertCartesian3ToPosition } from "./utils";

Expand Down Expand Up @@ -63,43 +62,6 @@ export default ({
// expose ref
const engineAPI = useEngineRef(ref, cesium);

// terrain
const terrainProperty = useMemo(
() => ({
terrain: property?.terrain?.terrain || property?.default?.terrain,
terrainType: property?.terrain?.terrainType || property?.default?.terrainType,
terrainExaggeration:
property?.terrain?.terrainExaggeration || property?.default?.terrainExaggeration,
terrainExaggerationRelativeHeight:
property?.terrain?.terrainExaggerationRelativeHeight ||
property?.default?.terrainExaggerationRelativeHeight,
depthTestAgainstTerrain:
property?.terrain?.depthTestAgainstTerrain || property?.default?.depthTestAgainstTerrain,
}),
[
property?.default?.terrain,
property?.default?.terrainType,
property?.default?.terrainExaggeration,
property?.default?.terrainExaggerationRelativeHeight,
property?.default?.depthTestAgainstTerrain,
property?.terrain?.terrain,
property?.terrain?.terrainType,
property?.terrain?.terrainExaggeration,
property?.terrain?.terrainExaggerationRelativeHeight,
property?.terrain?.depthTestAgainstTerrain,
],
);

const terrainProvider = useMemo((): TerrainProvider | undefined => {
const provider = terrainProperty.terrain
? terrainProperty.terrainType
? terrain[terrainProperty.terrainType] || terrain.default
: terrain.cesium
: terrain.default;
return typeof provider === "function" ? provider({ cesiumIonAccessToken }) : provider;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [cesiumIonAccessToken, terrainProperty.terrain, terrainProperty.terrainType]);

const backgroundColor = useMemo(
() =>
property?.default?.bgcolor ? Color.fromCssColorString(property.default.bgcolor) : undefined,
Expand Down Expand Up @@ -358,8 +320,6 @@ export default ({
useCameraLimiter(cesium, camera, property?.cameraLimiter);

return {
terrainProvider,
terrainProperty,
backgroundColor,
cesium,
cameraViewBoundaries,
Expand Down
16 changes: 2 additions & 14 deletions src/components/molecules/Visualizer/Engine/Cesium/index.tsx
Expand Up @@ -2,7 +2,6 @@ import { ArcType, Color, ScreenSpaceEventType } from "cesium";
import React, { forwardRef } from "react";
import {
Viewer,
Globe,
Fog,
Sun,
SkyAtmosphere,
Expand All @@ -19,6 +18,7 @@ import {
import type { EngineProps, Ref as EngineRef } from "..";

import Clock from "./core/Clock";
import Globe from "./core/Globe";
import ImageryLayers from "./core/Imagery";
import Indicator from "./core/Indicator";
import Event from "./Event";
Expand Down Expand Up @@ -50,8 +50,6 @@ const Cesium: React.ForwardRefRenderFunction<EngineRef, EngineProps> = (
ref,
) => {
const {
terrainProvider,
terrainProperty,
backgroundColor,
cesium,
cameraViewBoundaries,
Expand Down Expand Up @@ -175,17 +173,7 @@ const Cesium: React.ForwardRefRenderFunction<EngineRef, EngineProps> = (
/>
<Sun show={property?.atmosphere?.enable_sun ?? true} />
<SkyAtmosphere show={property?.atmosphere?.sky_atmosphere ?? true} />
<Globe
enableLighting={!!property?.atmosphere?.enable_lighting}
showGroundAtmosphere={property?.atmosphere?.ground_atmosphere ?? true}
atmosphereSaturationShift={property?.atmosphere?.surturation_shift}
atmosphereHueShift={property?.atmosphere?.hue_shift}
atmosphereBrightnessShift={property?.atmosphere?.brightness_shift}
terrainProvider={terrainProvider}
depthTestAgainstTerrain={!!terrainProperty.depthTestAgainstTerrain}
terrainExaggerationRelativeHeight={terrainProperty.terrainExaggerationRelativeHeight}
terrainExaggeration={terrainProperty.terrainExaggeration}
/>
<Globe property={property} cesiumIonAccessToken={cesiumIonAccessToken} />
{ready ? children : null}
</Viewer>
);
Expand Down
20 changes: 0 additions & 20 deletions src/components/molecules/Visualizer/Engine/Cesium/terrain.ts

This file was deleted.

27 changes: 14 additions & 13 deletions src/components/molecules/Visualizer/Engine/ref.ts
Expand Up @@ -134,20 +134,27 @@ export type ClusterProps = {
children?: ReactNode;
};

export type TerrainProperty = {
terrain?: boolean;
terrainType?: "cesium" | "arcgis" | "cesiumion"; // default: cesium
terrainExaggeration?: number; // default: 1
terrainExaggerationRelativeHeight?: number; // default: 0
depthTestAgainstTerrain?: boolean;
terrainCesiumIonAsset?: string;
terrainCesiumIonAccessToken?: string;
terrainCesiumIonUrl?: string;
terrainUrl?: string;
};

export type SceneProperty = {
default?: {
camera?: Camera;
terrain?: boolean;
terrainType?: "cesium" | "arcgis"; // default: cesium
terrainExaggeration?: number; // default: 1
terrainExaggerationRelativeHeight?: number; // default: 0
depthTestAgainstTerrain?: boolean;
allowEnterGround?: boolean;
skybox?: boolean;
bgcolor?: string;
ion?: string;
sceneMode?: SceneMode; // default: scene3d
};
} & TerrainProperty;
cameraLimiter?: {
cameraLimitterEnabled?: boolean;
cameraLimitterShowHelper?: boolean;
Expand All @@ -168,13 +175,7 @@ export type SceneProperty = {
tile_minLevel?: number;
tile_opacity?: number;
}[];
terrain?: {
terrain?: boolean;
terrainType?: "cesium" | "arcgis"; // default: cesium
terrainExaggeration?: number; // default: 1
terrainExaggerationRelativeHeight?: number; // default: 0
depthTestAgainstTerrain?: boolean;
};
terrain?: TerrainProperty;
atmosphere?: {
enable_sun?: boolean;
enable_lighting?: boolean;
Expand Down
9 changes: 9 additions & 0 deletions src/util/util.ts
@@ -1,5 +1,14 @@
import { Args, Args3, Args2 } from "@reearth/types";

/**
* Often we want to make an array of keys of an object type,
* but if we just specify the key names directly, we may forget to change the array if the object type is changed.
* With this function, the compiler checks the object keys for completeness, so the array of keys is always up to date.
*/
export const objKeys = <T>(obj: { [k in keyof T]: 0 }): (keyof T)[] => {
return Object.keys(obj) as (keyof T)[];
};

export const isPresent = <V>(v: V | undefined): v is V => typeof v !== "undefined";

export const partitionObject = <T extends {}, K extends keyof T>(
Expand Down
6 changes: 3 additions & 3 deletions yarn.lock
Expand Up @@ -2262,9 +2262,9 @@
"@types/gapi.client.discovery" "*"

"@maxim_mazurok/gapi.client.sheets-v4@latest":
version "0.0.20221031"
resolved "https://registry.yarnpkg.com/@maxim_mazurok/gapi.client.sheets-v4/-/gapi.client.sheets-v4-0.0.20221031.tgz#f586b972a7897afadf6f8b49c0336f0c944a6a1f"
integrity sha512-BxEMZ7l0C7csdKLmSSRwk9SyM8PaSQirrgEYTya34pWRKAfYgdrUpA2NnN4iSXbdWluohuBcBcZj920FSqy0WQ==
version "0.0.20221115"
resolved "https://registry.yarnpkg.com/@maxim_mazurok/gapi.client.sheets-v4/-/gapi.client.sheets-v4-0.0.20221115.tgz#5bd60c2dfb780167dbe5d0ee690f7139e1854aa9"
integrity sha512-xMLfeiYJx3HWBybGDSlU/RHShY/0oXaoI5qLmchOJBRslEYbLFF2o7TJgR5JWTuG7mj3n+QtjZhV7FGoyU5/og==
dependencies:
"@types/gapi.client" "*"
"@types/gapi.client.discovery" "*"
Expand Down

0 comments on commit e0b99a6

Please sign in to comment.