diff --git a/src/r3f/components/CameraControls.jsx b/src/r3f/components/CameraControls.jsx index b25cb9ce5..6ff0f1183 100644 --- a/src/r3f/components/CameraControls.jsx +++ b/src/r3f/components/CameraControls.jsx @@ -2,13 +2,13 @@ import { forwardRef, useMemo, useEffect, useContext } from 'react'; import { useThree, useFrame } from '@react-three/fiber'; import { EnvironmentControls as EnvironmentControlsImpl, GlobeControls as GlobeControlsImpl } from '3d-tiles-renderer/three'; import { useShallowOptions } from '../utilities/useOptions.js'; -import { TilesRendererContext } from './TilesRenderer.jsx'; +import { EllipsoidContext } from './TilesRenderer.jsx'; import { useApplyRefs } from '../utilities/useApplyRefs.js'; // Add a base component implementation for both EnvironmentControls and GlobeControls const ControlsBaseComponent = forwardRef( function ControlsBaseComponent( props, ref ) { - const { controlsConstructor, domElement, scene, camera, ellipsoid, ellipsoidFrame, tilesRenderer, ...rest } = props; + const { controlsConstructor, domElement, scene, camera, ellipsoid, ellipsoidFrame, ...rest } = props; const [ defaultCamera ] = useThree( state => [ state.camera ] ); const [ gl ] = useThree( state => [ state.gl ] ); @@ -17,13 +17,12 @@ const ControlsBaseComponent = forwardRef( function ControlsBaseComponent( props, const [ get ] = useThree( state => [ state.get ] ); const [ set ] = useThree( state => [ state.set ] ); - const contextTilesRenderer = useContext( TilesRendererContext ); - const appliedTilesRenderer = tilesRenderer || contextTilesRenderer; + const ellipsoidContext = useContext( EllipsoidContext ); const appliedCamera = camera || defaultCamera || null; const appliedScene = scene || defaultScene || null; const appliedDomElement = domElement || gl.domElement || null; - const appliedEllipsoid = ellipsoid || appliedTilesRenderer?.ellipsoid || null; - const appliedEllipsoidFrame = ellipsoidFrame || appliedTilesRenderer?.group || null; + const appliedEllipsoid = ellipsoid || ellipsoidContext?.ellipsoid || null; + const appliedEllipsoidFrame = ellipsoidFrame || ellipsoidContext?.frame || null; // create a controls instance const controls = useMemo( () => { diff --git a/src/r3f/components/CompassGizmo.jsx b/src/r3f/components/CompassGizmo.jsx index 828084221..324d76d77 100644 --- a/src/r3f/components/CompassGizmo.jsx +++ b/src/r3f/components/CompassGizmo.jsx @@ -1,7 +1,7 @@ import { createPortal, useFrame, useThree } from '@react-three/fiber'; import { useContext, useEffect, useMemo, useRef, useState } from 'react'; import { BackSide, Matrix4, OrthographicCamera, Ray, Scene, Vector3 } from 'three'; -import { TilesRendererContext } from './TilesRenderer.jsx'; +import { EllipsoidContext } from './TilesRenderer.jsx'; // Based in part on @pmndrs/drei's Gizmo component @@ -152,7 +152,7 @@ function CompassGraphic( { northColor = 0xEF5350, southColor = 0xFFFFFF } ) { export function CompassGizmo( { children, overrideRenderLoop, mode = '3d', margin = 10, scale = 35, visible = true, ...rest } ) { const [ defaultCamera, defaultScene, size ] = useThree( state => [ state.camera, state.scene, state.size ] ); - const tiles = useContext( TilesRendererContext ); + const ellipsoidContext = useContext( EllipsoidContext ); const groupRef = useRef( null ); const scene = useMemo( () => { @@ -175,22 +175,24 @@ export function CompassGizmo( { children, overrideRenderLoop, mode = '3d', margi useFrame( () => { - if ( tiles === null || groupRef.current === null ) { + const ellipsoid = ellipsoidContext?.ellipsoid; + const frame = ellipsoidContext?.frame; + + if ( ( ! ellipsoid || ! frame ) || groupRef.current === null ) { return null; } - const { ellipsoid } = tiles; const group = groupRef.current; // get the ENU frame in world space - getCameraFocusPoint( defaultCamera, ellipsoid, tiles.group, _pos ).applyMatrix4( tiles.group.matrixWorldInverse ); + getCameraFocusPoint( defaultCamera, ellipsoid, frame, _pos ).applyMatrix4( frame.matrixWorldInverse ); ellipsoid.getPositionToCartographic( _pos, _cart ); ellipsoid .getEastNorthUpFrame( _cart.lat, _cart.lon, 0, _enuMatrix ) - .premultiply( tiles.group.matrixWorld ); + .premultiply( frame.matrixWorld ); // get the camera orientation in the local ENU frame _enuMatrix.invert(); diff --git a/src/r3f/components/TilesRenderer.jsx b/src/r3f/components/TilesRenderer.jsx index 2ae7e9c6e..cb08faa32 100644 --- a/src/r3f/components/TilesRenderer.jsx +++ b/src/r3f/components/TilesRenderer.jsx @@ -1,4 +1,4 @@ -import { createContext, useContext, useEffect, useRef, forwardRef, useCallback, useState, useLayoutEffect, useReducer } from 'react'; +import { createContext, useMemo, useContext, useEffect, useRef, forwardRef, useCallback, useState, useLayoutEffect, useReducer } from 'react'; import { useThree, useFrame } from '@react-three/fiber'; import { Object3D } from 'three'; import { TilesRenderer as TilesRendererImpl, WGS84_ELLIPSOID } from '3d-tiles-renderer/three'; @@ -10,6 +10,9 @@ import { useApplyRefs } from '../utilities/useApplyRefs.js'; export const TilesRendererContext = createContext( null ); export const TilesPluginContext = createContext( null ); +// context for accessing just ellipsoid and frame data +export const EllipsoidContext = createContext( null ); + // group that matches the transform of the tileset root group function TileSetRoot( { children } ) { @@ -284,6 +287,16 @@ export const TilesRenderer = forwardRef( function TilesRenderer( props, ref ) { // assign options recursively useDeepOptions( tiles, options ); + const ellipsoidContextValue = useMemo( () => { + + if ( ! tiles ) return null; + + return { + ellipsoid: tiles.ellipsoid, + frame: tiles.group, + }; + + }, [ tiles?.ellipsoid, tiles?.group ] ); // only render out the tiles once the instance and context are ready if ( ! tiles ) { @@ -295,9 +308,11 @@ export const TilesRenderer = forwardRef( function TilesRenderer( props, ref ) { return <> - - { children } - + + + { children } + + ;