Skip to content

Commit

Permalink
chore(web): enable visualizer explicit rendering (#583)
Browse files Browse the repository at this point in the history
Co-authored-by: keiya sasaki <keiya.s.0210@gmail.com>
  • Loading branch information
airslice and keiya01 committed Jul 31, 2023
1 parent 1ebef7e commit 7a25032
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 20 deletions.
10 changes: 10 additions & 0 deletions web/src/beta/lib/core/Map/Layers/hooks.ts
Expand Up @@ -9,6 +9,7 @@ import {
useMemo,
useRef,
useState,
type MutableRefObject,
} from "react";
import { useSet } from "react-use";
import { v4 as uuidv4 } from "uuid";
Expand All @@ -18,6 +19,8 @@ import { objectFromGetter } from "@reearth/beta/utils/object";

import { computeAtom, convertLegacyLayer, SelectedFeatureInfo } from "../../mantle";
import type { Atom, ComputedLayer, Layer, NaiveLayer } from "../../mantle";
import { FORCE_REQUEST_RENDER, REQUEST_RENDER_ONCE } from "../hooks";
import { RequestingRenderMode } from "../types";
import { useGet } from "../utils";

import { computedLayerKeys, layerKeys } from "./keys";
Expand Down Expand Up @@ -99,6 +102,7 @@ export default function useHooks({
hiddenLayers,
selectedLayerId,
selectionReason,
requestingRenderMode,
onLayerSelect,
}: {
layers?: Layer[];
Expand All @@ -109,6 +113,7 @@ export default function useHooks({
featureId?: string;
};
selectionReason?: LayerSelectionReason;
requestingRenderMode?: MutableRefObject<RequestingRenderMode>;
onLayerSelect?: (
layerId: string | undefined,
featureId: string | undefined,
Expand Down Expand Up @@ -561,6 +566,11 @@ export default function useHooks({
setOverridenLayers(layers => layers.filter(l => !deleted.includes(l.id)));
}, [atomMap, layers, layerMap, lazyLayerMap, setOverridenLayers, showLayer]);

useEffect(() => {
if (!requestingRenderMode || requestingRenderMode.current === FORCE_REQUEST_RENDER) return;
requestingRenderMode.current = REQUEST_RENDER_ONCE;
}, [flattenedLayers, overriddenLayers, hiddenLayerIds, requestingRenderMode]);

return { atomMap, flattenedLayers, isHidden };
}

Expand Down
16 changes: 13 additions & 3 deletions web/src/beta/lib/core/Map/Layers/index.tsx
@@ -1,9 +1,9 @@
import { forwardRef, type ForwardRefRenderFunction } from "react";
import { forwardRef, type ForwardRefRenderFunction, type MutableRefObject } from "react";

import { SelectedFeatureInfo } from "@reearth/beta/lib/core/mantle";

import ClusteredLayers, { type Props as ClusteredLayerProps } from "../ClusteredLayers";
import type { ComputedLayer } from "../types";
import type { ComputedLayer, RequestingRenderMode } from "../types";

import useHooks, { LayerSelectionReason, type Ref } from "./hooks";

Expand Down Expand Up @@ -38,6 +38,7 @@ export type Props = Omit<ClusteredLayerProps, "atomMap" | "isHidden"> & {
};
selectionReason?: LayerSelectionReason;
sceneProperty?: any;
requestingRenderMode?: MutableRefObject<RequestingRenderMode>;
onLayerSelect?: (
layerId: string | undefined,
featureId: string | undefined,
Expand All @@ -48,7 +49,15 @@ export type Props = Omit<ClusteredLayerProps, "atomMap" | "isHidden"> & {
};

const Layers: ForwardRefRenderFunction<Ref, Props> = (
{ layers, hiddenLayers, selectedLayerId, selectionReason, onLayerSelect, ...props },
{
layers,
hiddenLayers,
selectedLayerId,
selectionReason,
requestingRenderMode,
onLayerSelect,
...props
},
ref,
) => {
const { atomMap, flattenedLayers, isHidden } = useHooks({
Expand All @@ -57,6 +66,7 @@ const Layers: ForwardRefRenderFunction<Ref, Props> = (
hiddenLayers,
selectedLayerId,
selectionReason,
requestingRenderMode,
onLayerSelect,
});

Expand Down
14 changes: 13 additions & 1 deletion web/src/beta/lib/core/Map/hooks.ts
Expand Up @@ -3,10 +3,20 @@ import { useImperativeHandle, useRef, type Ref, useState, useCallback, useEffect
import { SelectedFeatureInfo } from "../mantle";

import { type MapRef, mapRef } from "./ref";
import type { EngineRef, LayersRef, LayerSelectionReason, ComputedLayer } from "./types";
import type {
EngineRef,
LayersRef,
LayerSelectionReason,
ComputedLayer,
RequestingRenderMode,
} from "./types";

export type { MapRef } from "./ref";

export const FORCE_REQUEST_RENDER = -1;
export const NO_REQUEST_RENDER = 0;
export const REQUEST_RENDER_ONCE = 1;

export default function ({
ref,
onLayerSelect,
Expand All @@ -26,6 +36,7 @@ export default function ({
}) {
const engineRef = useRef<EngineRef>(null);
const layersRef = useRef<LayersRef>(null);
const requestingRenderMode = useRef<RequestingRenderMode>(NO_REQUEST_RENDER);

useImperativeHandle(
ref,
Expand Down Expand Up @@ -93,6 +104,7 @@ export default function ({
engineRef,
layersRef,
selectedLayer,
requestingRenderMode,
handleLayerSelect,
handleEngineLayerSelect,
};
Expand Down
20 changes: 14 additions & 6 deletions web/src/beta/lib/core/Map/index.tsx
Expand Up @@ -49,12 +49,18 @@ function Map(
): JSX.Element | null {
const currentEngine = engine ? engines?.[engine] : undefined;
const Engine = currentEngine?.component;
const { engineRef, layersRef, selectedLayer, handleLayerSelect, handleEngineLayerSelect } =
useHooks({
ref,
selectedLayerId,
onLayerSelect,
});
const {
engineRef,
layersRef,
selectedLayer,
requestingRenderMode,
handleLayerSelect,
handleEngineLayerSelect,
} = useHooks({
ref,
selectedLayerId,
onLayerSelect,
});

const selectedLayerIdForEngine = useMemo(
() => ({ layerId: selectedLayer.layerId, featureId: selectedLayer.featureId }),
Expand All @@ -70,6 +76,7 @@ function Map(
layerSelectionReason={selectedLayer.reason}
onLayerSelect={handleEngineLayerSelect}
layersRef={layersRef}
requestingRenderMode={requestingRenderMode}
{...props}>
<Layers
ref={layersRef}
Expand All @@ -86,6 +93,7 @@ function Map(
delegatedDataTypes={currentEngine.delegatedDataTypes}
meta={props.meta}
sceneProperty={props.property}
requestingRenderMode={requestingRenderMode}
onLayerSelect={handleLayerSelect}
/>
</Engine>
Expand Down
5 changes: 5 additions & 0 deletions web/src/beta/lib/core/Map/types/index.ts
Expand Up @@ -5,6 +5,7 @@ import type {
ReactNode,
CSSProperties,
RefObject,
MutableRefObject,
} from "react";

import type {
Expand Down Expand Up @@ -118,6 +119,7 @@ export type EngineProps = {
shouldRender?: boolean;
meta?: Record<string, unknown>;
layersRef?: RefObject<LayersRef>;
requestingRenderMode?: MutableRefObject<RequestingRenderMode>;
onLayerSelect?: (
layerId: string | undefined,
featureId?: string,
Expand Down Expand Up @@ -341,6 +343,7 @@ export type SceneProperty = {
};
render?: {
antialias?: "low" | "medium" | "high" | "extreme";
debugFramePerSecond?: boolean;
};
};

Expand All @@ -354,3 +357,5 @@ export type Engine = {
clusterComponent: ClusterComponentType;
delegatedDataTypes?: DataType[];
};

export type RequestingRenderMode = -1 | 0 | 1; // -1: force render on every postUpdate, 0: no request to render, 1: request one frame
4 changes: 4 additions & 0 deletions web/src/beta/lib/core/engines/Cesium/Feature/Box/hooks/box.ts
Expand Up @@ -77,8 +77,11 @@ export const useHooks = ({
}
}, [allowEnterGround, viewer, trs]);

const { requestRender } = useContext();

useEffect(() => {
updateTrs(trs, property, terrainHeightEstimate, geometry, allowEnterGround);
requestRender?.();
updateTerrainHeight();
}, [
property,
Expand All @@ -88,6 +91,7 @@ export const useHooks = ({
terrainHeightEstimate,
updateTerrainHeight,
allowEnterGround,
requestRender,
]);

const style = useMemo(
Expand Down
Expand Up @@ -6,6 +6,7 @@ import { ComputedFeature, evalFeature, Feature, guessType } from "@reearth/beta/
import { requestIdleCallbackWithRequiredWork } from "@reearth/beta/utils/idle";

import type { ResourceAppearance } from "../../..";
import { useContext } from "../context";
import {
attachTag,
extractSimpleLayerData,
Expand Down Expand Up @@ -72,6 +73,8 @@ export default function Resource({
const actualType = ext ? types[ext] : type !== "auto" ? type : undefined;
const Component = actualType ? comps[actualType] : undefined;

const { requestRender } = useContext();

const handleChange = useCallback(
(e: DataSource) => {
if (!viewer) return;
Expand All @@ -92,13 +95,14 @@ export default function Resource({
computedFeatures.push(computedFeature);
}
});
requestRender?.();

// GeoJSON is not delegated data, so we need to skip.
if (type !== "geojson") {
onComputedFeatureFetch?.(features, computedFeatures);
}
},
[layer, viewer, onComputedFeatureFetch, type],
[layer, viewer, onComputedFeatureFetch, type, requestRender],
);

const initialClock = useRef({
Expand Down
Expand Up @@ -36,6 +36,7 @@ import { layerIdField, sampleTerrainHeightFromCartesian } from "../../common";
import { arrayToCartecian3 } from "../../helpers/sphericalHaromic";
import type { InternalCesium3DTileFeature } from "../../types";
import { lookupFeatures, translationWithClamping } from "../../utils";
import { useContext } from "../context";
import {
usePick,
attachTag,
Expand Down Expand Up @@ -290,13 +291,16 @@ const useFeature = ({
[computeFeatureAsync],
);

const { requestRender } = useContext();

useEffect(() => {
const compute = async () => {
const startedComputingAt = Date.now();
await computeFeatures(startedComputingAt);
requestRender?.();
};
compute();
}, [computeFeatures]);
}, [computeFeatures, requestRender]);
};

export const useHooks = ({
Expand Down
1 change: 1 addition & 0 deletions web/src/beta/lib/core/engines/Cesium/Feature/context.ts
Expand Up @@ -9,6 +9,7 @@ export type Context = {
getCamera?: () => Camera | undefined;
flyTo?: (target: string | FlyToDestination, options?: CameraOptions) => void;
onLayerEdit?: (e: LayerEditEvent) => void;
requestRender?: () => void;
};

export const context = createContext<Context>({});
Expand Down
58 changes: 57 additions & 1 deletion web/src/beta/lib/core/engines/Cesium/hooks.ts
Expand Up @@ -20,7 +20,7 @@ import type { CesiumComponentRef, CesiumMovementEvent, RootEventTarget } from "r
import { useCustomCompareCallback } from "use-custom-compare";

import { ComputedFeature, DataType, SelectedFeatureInfo } from "@reearth/beta/lib/core/mantle";
import { LayersRef, FEATURE_FLAGS } from "@reearth/beta/lib/core/Map";
import { LayersRef, FEATURE_FLAGS, RequestingRenderMode } from "@reearth/beta/lib/core/Map";
import { e2eAccessToken, setE2ECesiumViewer } from "@reearth/services/config";

import type {
Expand All @@ -33,6 +33,7 @@ import type {
MouseEvents,
LayerEditEvent,
} from "..";
import { FORCE_REQUEST_RENDER, NO_REQUEST_RENDER, REQUEST_RENDER_ONCE } from "../../Map/hooks";

import { useCameraLimiter } from "./cameraLimiter";
import { getCamera, isDraggable, isSelectable, getLocationFromScreen } from "./common";
Expand All @@ -50,9 +51,12 @@ export default ({
selectedLayerId,
selectionReason,
isLayerDraggable,
isLayerDragging,
meta,
layersRef,
featureFlags,
requestingRenderMode,
shouldRender,
onLayerSelect,
onCameraChange,
onLayerDrag,
Expand All @@ -70,8 +74,11 @@ export default ({
layersRef?: RefObject<LayersRef>;
selectionReason?: LayerSelectionReason;
isLayerDraggable?: boolean;
isLayerDragging?: boolean;
meta?: Record<string, unknown>;
featureFlags: number;
requestingRenderMode?: React.MutableRefObject<RequestingRenderMode>;
shouldRender?: boolean;
onLayerSelect?: (
layerId?: string,
featureId?: string,
Expand Down Expand Up @@ -707,6 +714,7 @@ export default ({
flyTo: engineAPI.flyTo,
getCamera: engineAPI.getCamera,
onLayerEdit,
requestRender: engineAPI.requestRender,
}),
[selectionReason, engineAPI, onLayerEdit],
);
Expand Down Expand Up @@ -745,6 +753,54 @@ export default ({
: 1; // default as 1
}, [property?.render?.antialias]);

// explicit rendering
const explicitRender = useCallback(() => {
const viewer = cesium.current?.cesiumElement;
if (!requestingRenderMode?.current || !viewer || viewer.isDestroyed()) return;
viewer.scene.requestRender();
if (requestingRenderMode.current === REQUEST_RENDER_ONCE) {
requestingRenderMode.current = NO_REQUEST_RENDER;
}
}, [requestingRenderMode]);

const explicitRenderRef = useRef<() => void>();

useEffect(() => {
explicitRenderRef.current = explicitRender;
}, [explicitRender]);

useEffect(() => {
const viewer = cesium.current?.cesiumElement;
if (!viewer || viewer.isDestroyed()) return;
return viewer.scene.postUpdate.addEventListener(() => {
explicitRenderRef.current?.();
});
}, []);

// render one frame when scene property changes
useEffect(() => {
if (requestingRenderMode) {
requestingRenderMode.current = REQUEST_RENDER_ONCE;
}
}, [property, requestingRenderMode]);

// force render when timeline is animating or is shouldRender
// set maximumRenderTimeChange to 0 when is timeline animating
useEffect(() => {
const viewer = cesium.current?.cesiumElement;
if (!viewer || viewer.isDestroyed()) return;
viewer.scene.maximumRenderTimeChange = !property?.timeline?.animation ? Infinity : 0;

if (requestingRenderMode) {
requestingRenderMode.current =
isLayerDragging || shouldRender
? FORCE_REQUEST_RENDER
: requestingRenderMode.current === REQUEST_RENDER_ONCE
? REQUEST_RENDER_ONCE
: NO_REQUEST_RENDER;
}
}, [property?.timeline?.animation, isLayerDragging, shouldRender, requestingRenderMode]);

return {
backgroundColor,
cesium,
Expand Down

0 comments on commit 7a25032

Please sign in to comment.