Skip to content

Commit

Permalink
feat(react-components): Allow reading camera target instead of camera…
Browse files Browse the repository at this point in the history
… rotation from scene (#4221)

* Allow reading camera target instead of camera rotation from scene

* Extract extractCameraTarget into separate function

---------

Co-authored-by: cognite-bulldozer[bot] <51074376+cognite-bulldozer[bot]@users.noreply.github.com>
  • Loading branch information
anders-hopland and cognite-bulldozer[bot] authored Feb 20, 2024
1 parent 96f89a6 commit 97594b7
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 28 deletions.
10 changes: 1 addition & 9 deletions react-components/src/components/SceneContainer/Queries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,7 @@ export function createGetSceneQuery(sceneExternalId: string, sceneSpaceId: strin
externalId: 'SceneConfiguration',
version: 'v1'
},
properties: [
'name',
'cameraTranslationX',
'cameraTranslationY',
'cameraTranslationZ',
'cameraEulerRotationX',
'cameraEulerRotationY',
'cameraEulerRotationZ'
]
properties: ['*']
}
]
},
Expand Down
3 changes: 3 additions & 0 deletions react-components/src/components/SceneContainer/SceneTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ export type SceneConfiguration = {
cameraEulerRotationX: number;
cameraEulerRotationY: number;
cameraEulerRotationZ: number;
cameraTargetX?: number;
cameraTargetY?: number;
cameraTargetZ?: number;
};

export type CadOrPointCloudModel = Transformation3d & {
Expand Down
3 changes: 3 additions & 0 deletions react-components/src/hooks/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ export type SceneConfigurationProperties = {
cameraEulerRotationX: number;
cameraEulerRotationY: number;
cameraEulerRotationZ: number;
cameraTargetX?: number;
cameraTargetY?: number;
cameraTargetZ?: number;
};

export type SkyboxProperties = {
Expand Down
5 changes: 4 additions & 1 deletion react-components/src/hooks/useSceneConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ export const useSceneConfig = (
cameraTranslationZ: SceneConfigurationProperties.cameraTranslationZ,
cameraEulerRotationX: SceneConfigurationProperties.cameraEulerRotationX,
cameraEulerRotationY: SceneConfigurationProperties.cameraEulerRotationY,
cameraEulerRotationZ: SceneConfigurationProperties.cameraEulerRotationZ
cameraEulerRotationZ: SceneConfigurationProperties.cameraEulerRotationZ,
cameraTargetX: SceneConfigurationProperties.cameraTargetX,
cameraTargetY: SceneConfigurationProperties.cameraTargetY,
cameraTargetZ: SceneConfigurationProperties.cameraTargetZ
},
skybox: getSkybox(sceneResponse),
groundPlanes: getGroundPlanes(sceneResponse),
Expand Down
45 changes: 29 additions & 16 deletions react-components/src/hooks/useSceneDefaultCamera.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { useMemo } from 'react';
import { useSceneConfig } from './useSceneConfig';
import { Vector3, Quaternion, Euler, MathUtils, Box3 } from 'three';
import { useReveal } from '..';
import { CDF_TO_VIEWER_TRANSFORMATION } from '@cognite/reveal';
import { CDF_TO_VIEWER_TRANSFORMATION, type Cognite3DViewer } from '@cognite/reveal';
import { type SceneConfiguration } from '../components/SceneContainer/SceneTypes';

export const useSceneDefaultCamera = (
sceneExternalId: string,
Expand All @@ -26,33 +27,45 @@ export const useSceneDefaultCamera = (
data.sceneConfiguration.cameraTranslationZ
);

const target = extractCameraTarget(data.sceneConfiguration, viewer);
position.applyMatrix4(CDF_TO_VIEWER_TRANSFORMATION);
target.applyMatrix4(CDF_TO_VIEWER_TRANSFORMATION);

return {
fitCameraToSceneDefault: () => {
viewer.cameraManager.setCameraState({ position, target });
}
};
}, [viewer, data?.sceneConfiguration]);
};

function extractCameraTarget(scene: SceneConfiguration, viewer: Cognite3DViewer): Vector3 {
if (scene.cameraTargetX !== undefined) {
return new Vector3(scene.cameraTargetX, scene.cameraTargetY, scene.cameraTargetZ);
} else {
const rotation = new Quaternion().setFromEuler(
new Euler(
MathUtils.degToRad(data.sceneConfiguration.cameraEulerRotationX),
MathUtils.degToRad(data.sceneConfiguration.cameraEulerRotationY),
MathUtils.degToRad(data.sceneConfiguration.cameraEulerRotationZ),
MathUtils.degToRad(scene.cameraEulerRotationX),
MathUtils.degToRad(scene.cameraEulerRotationY),
MathUtils.degToRad(scene.cameraEulerRotationZ),
'XYZ'
)
);

const position = new Vector3(
scene.cameraTranslationX,
scene.cameraTranslationY,
scene.cameraTranslationZ
);
// As a heuristic, use distance to center of all models' bounding
// boxes as target distance
const positionToSceneCenterDistance = position.distanceTo(
viewer.models
.reduce((acc, m) => acc.union(m.getModelBoundingBox()), new Box3())
.getCenter(new Vector3())
);
const target = position
return position
.clone()
.add(new Vector3(0, 0, -positionToSceneCenterDistance).applyQuaternion(rotation));

position.applyMatrix4(CDF_TO_VIEWER_TRANSFORMATION);
target.applyMatrix4(CDF_TO_VIEWER_TRANSFORMATION);

return {
fitCameraToSceneDefault: () => {
viewer.cameraManager.setCameraState({ position, target });
}
};
}, [data, viewer]);
};
}
}
5 changes: 3 additions & 2 deletions react-components/stories/SceneContainer.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,14 @@ export const Main: Story = {
<RevealStoryContainer color={new Color(0x4a4a4a)} sdk={sdk}>
<MyCustomToolbar>
<RevealToolbar.ResetCameraButton
sceneExternalId={sceneExternalId}
sceneSpaceId={sceneSpaceId}
sceneExternalId={selectedScene?.externalId}
sceneSpaceId={selectedScene?.space}
/>
<RevealToolbar.SelectSceneButton
selectedScene={selectedScene}
setSelectedScene={setSelectedScene}
/>
<RevealToolbar.FitModelsButton />
</MyCustomToolbar>
<SceneContainerStoryContent
sceneExternalId={
Expand Down

0 comments on commit 97594b7

Please sign in to comment.