easy-three-utils 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/package.json +12 -0
  2. package/src/common/index.ts +24 -0
  3. package/src/common/useLine2.ts +87 -0
  4. package/src/common/useLoader.ts +184 -0
  5. package/src/common/useLocationCalculator.ts +145 -0
  6. package/src/common/useMark.ts +42 -0
  7. package/src/common/useTween.ts +86 -0
  8. package/src/core/basic/camera.ts +28 -0
  9. package/src/core/basic/clock.ts +11 -0
  10. package/src/core/basic/control.ts +32 -0
  11. package/src/core/basic/index.ts +35 -0
  12. package/src/core/basic/labelRenderer.ts +26 -0
  13. package/src/core/basic/light.ts +63 -0
  14. package/src/core/basic/renderer.ts +37 -0
  15. package/src/core/basic/scene.ts +11 -0
  16. package/src/core/basic/stats.ts +16 -0
  17. package/src/core/event.ts +74 -0
  18. package/src/core/index.ts +11 -0
  19. package/src/core/main.ts +389 -0
  20. package/src/draco/README.md +32 -0
  21. package/src/draco/draco_decoder.js +34 -0
  22. package/src/draco/draco_decoder.wasm +0 -0
  23. package/src/draco/draco_encoder.js +33 -0
  24. package/src/draco/draco_wasm_wrapper.js +117 -0
  25. package/src/draco/gltf/draco_decoder.js +33 -0
  26. package/src/draco/gltf/draco_decoder.wasm +0 -0
  27. package/src/draco/gltf/draco_encoder.js +33 -0
  28. package/src/draco/gltf/draco_wasm_wrapper.js +116 -0
  29. package/src/tileRenderer/base/Tile.d.ts +50 -0
  30. package/src/tileRenderer/base/TileBase.d.ts +76 -0
  31. package/src/tileRenderer/base/TileInternal.d.ts +36 -0
  32. package/src/tileRenderer/base/TilesRendererBase.d.ts +35 -0
  33. package/src/tileRenderer/base/TilesRendererBase.js +847 -0
  34. package/src/tileRenderer/base/Tileset.d.ts +66 -0
  35. package/src/tileRenderer/base/constants.d.ts +6 -0
  36. package/src/tileRenderer/base/constants.js +16 -0
  37. package/src/tileRenderer/base/loaders/B3DMLoaderBase.d.ts +18 -0
  38. package/src/tileRenderer/base/loaders/B3DMLoaderBase.js +85 -0
  39. package/src/tileRenderer/base/loaders/CMPTLoaderBase.d.ts +22 -0
  40. package/src/tileRenderer/base/loaders/CMPTLoaderBase.js +61 -0
  41. package/src/tileRenderer/base/loaders/I3DMLoaderBase.d.ts +21 -0
  42. package/src/tileRenderer/base/loaders/I3DMLoaderBase.js +130 -0
  43. package/src/tileRenderer/base/loaders/LoaderBase.d.ts +10 -0
  44. package/src/tileRenderer/base/loaders/LoaderBase.js +73 -0
  45. package/src/tileRenderer/base/loaders/PNTSLoaderBase.d.ts +17 -0
  46. package/src/tileRenderer/base/loaders/PNTSLoaderBase.js +82 -0
  47. package/src/tileRenderer/base/plugins/ImplicitTilingPlugin.js +12 -0
  48. package/src/tileRenderer/base/traverseFunctions.js +468 -0
  49. package/src/tileRenderer/gltf.js +144 -0
  50. package/src/tileRenderer/index.d.ts +41 -0
  51. package/src/tileRenderer/index.js +44 -0
  52. package/src/tileRenderer/plugins/README.md +578 -0
  53. package/src/tileRenderer/plugins/base/ImplicitTilingPlugin.d.ts +2 -0
  54. package/src/tileRenderer/plugins/base/ImplicitTilingPlugin.js +84 -0
  55. package/src/tileRenderer/plugins/base/SUBTREELoader.js +876 -0
  56. package/src/tileRenderer/plugins/index.d.ts +17 -0
  57. package/src/tileRenderer/plugins/index.js +17 -0
  58. package/src/tileRenderer/plugins/three/CesiumIonAuthPlugin.d.ts +9 -0
  59. package/src/tileRenderer/plugins/three/CesiumIonAuthPlugin.js +175 -0
  60. package/src/tileRenderer/plugins/three/DebugTilesPlugin.d.ts +29 -0
  61. package/src/tileRenderer/plugins/three/DebugTilesPlugin.js +677 -0
  62. package/src/tileRenderer/plugins/three/GLTFExtensionsPlugin.d.ts +18 -0
  63. package/src/tileRenderer/plugins/three/GLTFExtensionsPlugin.js +86 -0
  64. package/src/tileRenderer/plugins/three/GoogleAttributionsManager.js +62 -0
  65. package/src/tileRenderer/plugins/three/GoogleCloudAuthPlugin.d.ts +5 -0
  66. package/src/tileRenderer/plugins/three/GoogleCloudAuthPlugin.js +200 -0
  67. package/src/tileRenderer/plugins/three/ReorientationPlugin.d.ts +12 -0
  68. package/src/tileRenderer/plugins/three/ReorientationPlugin.js +136 -0
  69. package/src/tileRenderer/plugins/three/TileCompressionPlugin.d.ts +18 -0
  70. package/src/tileRenderer/plugins/three/TileCompressionPlugin.js +223 -0
  71. package/src/tileRenderer/plugins/three/UpdateOnChangePlugin.d.ts +5 -0
  72. package/src/tileRenderer/plugins/three/UpdateOnChangePlugin.js +87 -0
  73. package/src/tileRenderer/plugins/three/fade/FadeManager.js +370 -0
  74. package/src/tileRenderer/plugins/three/fade/TilesFadePlugin.d.ts +9 -0
  75. package/src/tileRenderer/plugins/three/fade/TilesFadePlugin.js +318 -0
  76. package/src/tileRenderer/plugins/three/gltf/GLTFCesiumRTCExtension.d.ts +5 -0
  77. package/src/tileRenderer/plugins/three/gltf/GLTFCesiumRTCExtension.js +27 -0
  78. package/src/tileRenderer/plugins/three/gltf/GLTFMeshFeaturesExtension.d.ts +30 -0
  79. package/src/tileRenderer/plugins/three/gltf/GLTFMeshFeaturesExtension.js +76 -0
  80. package/src/tileRenderer/plugins/three/gltf/GLTFStructuralMetadataExtension.d.ts +49 -0
  81. package/src/tileRenderer/plugins/three/gltf/GLTFStructuralMetadataExtension.js +147 -0
  82. package/src/tileRenderer/plugins/three/gltf/metadata/classes/ClassProperty.js +149 -0
  83. package/src/tileRenderer/plugins/three/gltf/metadata/classes/MeshFeatures.js +215 -0
  84. package/src/tileRenderer/plugins/three/gltf/metadata/classes/PropertyAttributeAccessor.js +107 -0
  85. package/src/tileRenderer/plugins/three/gltf/metadata/classes/PropertySetAccessor.js +45 -0
  86. package/src/tileRenderer/plugins/three/gltf/metadata/classes/PropertyTableAccessor.js +209 -0
  87. package/src/tileRenderer/plugins/three/gltf/metadata/classes/PropertyTextureAccessor.js +244 -0
  88. package/src/tileRenderer/plugins/three/gltf/metadata/classes/StructuralMetadata.js +202 -0
  89. package/src/tileRenderer/plugins/three/gltf/metadata/math/Matrix2.js +55 -0
  90. package/src/tileRenderer/plugins/three/gltf/metadata/utilities/ClassPropertyHelpers.js +495 -0
  91. package/src/tileRenderer/plugins/three/gltf/metadata/utilities/TexCoordUtilities.js +72 -0
  92. package/src/tileRenderer/plugins/three/gltf/metadata/utilities/TextureReadUtility.js +154 -0
  93. package/src/tileRenderer/plugins/three/objects/EllipsoidRegionHelper.js +186 -0
  94. package/src/tileRenderer/plugins/three/objects/SphereHelper.js +55 -0
  95. package/src/tileRenderer/r3f/README.md +238 -0
  96. package/src/tileRenderer/r3f/components/CameraControls.jsx +132 -0
  97. package/src/tileRenderer/r3f/components/CameraTransition.jsx +177 -0
  98. package/src/tileRenderer/r3f/components/CanvasDOMOverlay.jsx +54 -0
  99. package/src/tileRenderer/r3f/components/CompassGizmo.jsx +260 -0
  100. package/src/tileRenderer/r3f/components/TilesAttributionOverlay.jsx +110 -0
  101. package/src/tileRenderer/r3f/components/TilesRenderer.jsx +239 -0
  102. package/src/tileRenderer/r3f/index.jsx +6 -0
  103. package/src/tileRenderer/r3f/utilities/useForceUpdate.jsx +8 -0
  104. package/src/tileRenderer/r3f/utilities/useObjectDep.jsx +59 -0
  105. package/src/tileRenderer/r3f/utilities/useOptions.jsx +143 -0
  106. package/src/tileRenderer/three/DebugTilesRenderer.d.ts +28 -0
  107. package/src/tileRenderer/three/DebugTilesRenderer.js +58 -0
  108. package/src/tileRenderer/three/TilesGroup.d.ts +9 -0
  109. package/src/tileRenderer/three/TilesGroup.js +91 -0
  110. package/src/tileRenderer/three/TilesRenderer.d.ts +37 -0
  111. package/src/tileRenderer/three/TilesRenderer.js +1049 -0
  112. package/src/tileRenderer/three/controls/CameraTransitionManager.js +305 -0
  113. package/src/tileRenderer/three/controls/EnvironmentControls.js +1295 -0
  114. package/src/tileRenderer/three/controls/GlobeControls.js +684 -0
  115. package/src/tileRenderer/three/controls/PivotPointMesh.js +104 -0
  116. package/src/tileRenderer/three/controls/PointerTracker.js +257 -0
  117. package/src/tileRenderer/three/controls/utils.js +113 -0
  118. package/src/tileRenderer/three/loaders/B3DMLoader.d.ts +26 -0
  119. package/src/tileRenderer/three/loaders/B3DMLoader.js +85 -0
  120. package/src/tileRenderer/three/loaders/CMPTLoader.d.ts +19 -0
  121. package/src/tileRenderer/three/loaders/CMPTLoader.js +97 -0
  122. package/src/tileRenderer/three/loaders/GLTFExtensionLoader.d.ts +11 -0
  123. package/src/tileRenderer/three/loaders/GLTFExtensionLoader.js +68 -0
  124. package/src/tileRenderer/three/loaders/I3DMLoader.d.ts +26 -0
  125. package/src/tileRenderer/three/loaders/I3DMLoader.js +256 -0
  126. package/src/tileRenderer/three/loaders/PNTSLoader.d.ts +25 -0
  127. package/src/tileRenderer/three/loaders/PNTSLoader.js +202 -0
  128. package/src/tileRenderer/three/loaders/gltf/GLTFCesiumRTCExtension.js +12 -0
  129. package/src/tileRenderer/three/loaders/gltf/GLTFMeshFeaturesExtension.js +12 -0
  130. package/src/tileRenderer/three/loaders/gltf/GLTFStructuralMetadataExtension.js +12 -0
  131. package/src/tileRenderer/three/math/Ellipsoid.d.ts +31 -0
  132. package/src/tileRenderer/three/math/Ellipsoid.js +337 -0
  133. package/src/tileRenderer/three/math/EllipsoidRegion.d.ts +23 -0
  134. package/src/tileRenderer/three/math/EllipsoidRegion.js +178 -0
  135. package/src/tileRenderer/three/math/ExtendedFrustum.js +65 -0
  136. package/src/tileRenderer/three/math/GeoConstants.d.ts +4 -0
  137. package/src/tileRenderer/three/math/GeoConstants.js +5 -0
  138. package/src/tileRenderer/three/math/GeoUtils.d.ts +9 -0
  139. package/src/tileRenderer/three/math/GeoUtils.js +106 -0
  140. package/src/tileRenderer/three/math/OBB.js +179 -0
  141. package/src/tileRenderer/three/math/TileBoundingVolume.js +272 -0
  142. package/src/tileRenderer/three/plugins/CesiumIonAuthPlugin.js +12 -0
  143. package/src/tileRenderer/three/plugins/DebugTilesPlugin.js +26 -0
  144. package/src/tileRenderer/three/plugins/GoogleCloudAuthPlugin.js +12 -0
  145. package/src/tileRenderer/three/raycastTraverse.js +178 -0
  146. package/src/tileRenderer/three/renderers/CesiumIonTilesRenderer.d.ts +14 -0
  147. package/src/tileRenderer/three/renderers/CesiumIonTilesRenderer.js +21 -0
  148. package/src/tileRenderer/three/renderers/GoogleTilesRenderer.d.ts +43 -0
  149. package/src/tileRenderer/three/renderers/GoogleTilesRenderer.js +48 -0
  150. package/src/tileRenderer/three/utilities.js +54 -0
  151. package/src/tileRenderer/utilities/BatchTable.d.ts +24 -0
  152. package/src/tileRenderer/utilities/BatchTable.js +82 -0
  153. package/src/tileRenderer/utilities/BatchTableHierarchyExtension.js +127 -0
  154. package/src/tileRenderer/utilities/FeatureTable.d.ts +30 -0
  155. package/src/tileRenderer/utilities/FeatureTable.js +159 -0
  156. package/src/tileRenderer/utilities/LRUCache.d.ts +8 -0
  157. package/src/tileRenderer/utilities/LRUCache.js +385 -0
  158. package/src/tileRenderer/utilities/PriorityQueue.d.ts +16 -0
  159. package/src/tileRenderer/utilities/PriorityQueue.js +137 -0
  160. package/src/tileRenderer/utilities/arrayToString.js +7 -0
  161. package/src/tileRenderer/utilities/readMagicBytes.js +29 -0
  162. package/src/tileRenderer/utilities/rgb565torgb.js +22 -0
  163. package/src/tileRenderer/utilities/urlExtension.js +34 -0
  164. package/tsconfig.json +42 -0
  165. package/tsconfig.node.json +11 -0
  166. package/typings/three.d.ts +27 -0
@@ -0,0 +1,177 @@
1
+ import { forwardRef, useEffect, useMemo } from 'react';
2
+ import { useFrame, useThree } from '@react-three/fiber';
3
+ import { CameraTransitionManager } from '3d-tiles-renderer';
4
+
5
+ export const CameraTransition = forwardRef( function CameraTransition( props, ref ) {
6
+
7
+ const { mode = 'perspective', onTransitionStart, onTransitionEnd, perspectiveCamera, orthographicCamera } = props;
8
+ const [ set, invalidate, controls, camera, size ] = useThree( state => [ state.set, state.invalidate, state.controls, state.camera, state.size ] );
9
+
10
+ // create the manager
11
+ const manager = useMemo( () => {
12
+
13
+ const manager = new CameraTransitionManager();
14
+ manager.autoSync = false;
15
+
16
+ if ( camera.isOrthographicCamera ) {
17
+
18
+ manager.orthographicCamera.copy( camera );
19
+ manager.mode = 'orthographic';
20
+
21
+ } else {
22
+
23
+ manager.perspectiveCamera.copy( camera );
24
+
25
+ }
26
+
27
+ manager.syncCameras();
28
+ manager.mode = mode;
29
+
30
+ return manager;
31
+
32
+ // only respect the camera initially so the default camera settings are automatically used
33
+
34
+ }, [] );
35
+
36
+ useEffect( () => {
37
+
38
+ const { perspectiveCamera, orthographicCamera } = manager;
39
+ const aspect = size.width / size.height;
40
+ perspectiveCamera.aspect = aspect;
41
+ perspectiveCamera.updateProjectionMatrix();
42
+
43
+ orthographicCamera.left = - orthographicCamera.top * aspect;
44
+ orthographicCamera.right = - orthographicCamera.left;
45
+ perspectiveCamera.updateProjectionMatrix();
46
+
47
+ }, [ manager, size ] );
48
+
49
+ // assign ref
50
+ useEffect( () => {
51
+
52
+ if ( ref ) {
53
+
54
+ if ( ref instanceof Function ) {
55
+
56
+ ref( manager );
57
+
58
+ } else {
59
+
60
+ ref.current = manager;
61
+
62
+ }
63
+
64
+ }
65
+
66
+ }, [ manager, ref ] );
67
+
68
+ // set the camera
69
+ useEffect( () => {
70
+
71
+ const cameraCallback = ( { camera } ) => {
72
+
73
+ set( () => ( { camera } ) );
74
+
75
+ };
76
+
77
+ set( () => ( { camera: manager.camera } ) );
78
+ manager.addEventListener( 'camera-change', cameraCallback );
79
+ return () => {
80
+
81
+ manager.removeEventListener( 'camera-change', cameraCallback );
82
+
83
+ };
84
+
85
+ }, [ manager, set ] );
86
+
87
+ // register for events
88
+ useEffect( () => {
89
+
90
+ if ( onTransitionEnd ) {
91
+
92
+ manager.addEventListener( 'transition-end', onTransitionEnd );
93
+ return () => manager.removeEventListener( 'transition-end', onTransitionEnd );
94
+
95
+ }
96
+
97
+ }, [ onTransitionEnd, manager ] );
98
+
99
+ useEffect( () => {
100
+
101
+ if ( onTransitionStart ) {
102
+
103
+ manager.addEventListener( 'transition-start', onTransitionStart );
104
+ return () => manager.removeEventListener( 'transition-start', onTransitionStart );
105
+
106
+ }
107
+
108
+ }, [ onTransitionStart, manager ] );
109
+
110
+ // assign cameras
111
+ useEffect( () => {
112
+
113
+ const oldPerspectiveCamera = manager.perspectiveCamera;
114
+ const oldOrthographicCamera = manager.orthographicCamera;
115
+ manager.perspectiveCamera = perspectiveCamera || oldPerspectiveCamera;
116
+ manager.orthographicCamera = orthographicCamera || oldOrthographicCamera;
117
+
118
+ set( () => ( { camera: manager.camera } ) );
119
+
120
+ return () => {
121
+
122
+ manager.perspectiveCamera = oldPerspectiveCamera;
123
+ manager.orthographicCamera = oldOrthographicCamera;
124
+
125
+ };
126
+
127
+ }, [ perspectiveCamera, orthographicCamera, manager, set ] );
128
+
129
+ // toggle
130
+ useEffect( () => {
131
+
132
+ if ( mode !== manager.mode ) {
133
+
134
+ if ( controls && controls.isEnvironmentControls ) {
135
+
136
+ controls.getPivotPoint( manager.fixedPoint );
137
+ manager.syncCameras();
138
+ controls.adjustCamera( manager.perspectiveCamera );
139
+ controls.adjustCamera( manager.orthographicCamera );
140
+
141
+ } else {
142
+
143
+ manager.fixedPoint
144
+ .set( 0, 0, - 1 )
145
+ .transformDirection( manager.camera.matrixWorld )
146
+ .multiplyScalar( 50 )
147
+ .add( manager.camera.position );
148
+ manager.syncCameras();
149
+
150
+ }
151
+
152
+ manager.toggle();
153
+ invalidate();
154
+
155
+ }
156
+
157
+ }, [ mode, manager, invalidate, controls ] );
158
+
159
+ // update animation
160
+ useFrame( () => {
161
+
162
+ manager.update();
163
+ if ( controls ) {
164
+
165
+ controls.enabled = ! manager.animating;
166
+
167
+ }
168
+
169
+ if ( manager.animating ) {
170
+
171
+ invalidate();
172
+
173
+ }
174
+
175
+ }, - 1 );
176
+
177
+ } );
@@ -0,0 +1,54 @@
1
+ import { useMemo, useEffect, StrictMode } from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import { useThree } from '@react-three/fiber';
4
+
5
+ // Utility class for overlaying dom elements on top of the canvas
6
+ export function CanvasDOMOverlay( { children, ...rest } ) {
7
+
8
+ // create the dom element and react root
9
+ const [ gl ] = useThree( state => [ state.gl ] );
10
+ const container = useMemo( () => document.createElement( 'div' ), [] );
11
+ const root = useMemo( () => createRoot( container ), [ container ] );
12
+
13
+ // watch for canvas resize
14
+ const observer = useMemo( () => {
15
+
16
+ const observer = new ResizeObserver( ( [ { contentRect } ] ) => {
17
+
18
+ container.style.top = `${ contentRect.top }px`;
19
+ container.style.left = `${ contentRect.left }px`;
20
+ container.style.width = `${ contentRect.width }px`;
21
+ container.style.height = `${ contentRect.height }px`;
22
+
23
+ } );
24
+ observer.observe( gl.domElement );
25
+ return observer;
26
+
27
+ }, [ gl, container ] );
28
+
29
+ // position the container
30
+ useEffect( () => {
31
+
32
+ container.style.pointerEvents = 'none';
33
+ container.style.position = 'absolute';
34
+ document.body.appendChild( container );
35
+
36
+ return () => {
37
+
38
+ container.remove();
39
+ observer.disconnect();
40
+
41
+ };
42
+
43
+ }, [ observer, container ] );
44
+
45
+ // render the children into the container
46
+ root.render(
47
+ <StrictMode>
48
+ <div { ...rest }>
49
+ { children }
50
+ </div>
51
+ </StrictMode>
52
+ );
53
+
54
+ }
@@ -0,0 +1,260 @@
1
+ import { createPortal, useFrame, useThree } from '@react-three/fiber';
2
+ import { useContext, useEffect, useMemo, useRef, useState } from 'react';
3
+ import { BackSide, Matrix4, OrthographicCamera, Ray, Scene, Vector3 } from 'three';
4
+ import { TilesRendererContext } from './TilesRenderer';
5
+ import { closestRayEllipsoidSurfacePointEstimate } from '../../three/controls/utils';
6
+
7
+ // Based in part on @pmndrs/drei's Gizmo component
8
+
9
+ const _vec = /*@__PURE__*/ new Vector3();
10
+ const _axis = /*@__PURE__*/ new Vector3();
11
+ const _pos = /*@__PURE__*/ new Vector3();
12
+ const _matrix = /*@__PURE__*/ new Matrix4();
13
+ const _invMatrix = /*@__PURE__*/ new Matrix4();
14
+ const _enuMatrix = /*@__PURE__*/ new Matrix4();
15
+ const _ray = /*@__PURE__*/ new Ray();
16
+ const _cart = {};
17
+
18
+ // Returns the "focus" point that the camera is facing based on the closest point to the ellipsoid.
19
+ // Used for determining the compass orientation.
20
+ function getCameraFocusPoint( camera, ellipsoid, tilesGroup, target ) {
21
+
22
+ _invMatrix.copy( tilesGroup.matrixWorld ).invert();
23
+
24
+ // get ray in globe coordinate frame
25
+ _ray.origin.copy( camera.position );
26
+ _ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
27
+ _ray.applyMatrix4( _invMatrix );
28
+
29
+ // get the closest point to the ray on the globe in the global coordinate frame
30
+ closestRayEllipsoidSurfacePointEstimate( _ray, ellipsoid, _pos );
31
+ _pos.applyMatrix4( tilesGroup.matrixWorld );
32
+
33
+ // get ortho camera info
34
+ _axis.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
35
+
36
+ // ensure we move the camera exactly along the forward vector to avoid shifting
37
+ // the camera in other directions due to floating point error
38
+ const dist = _pos.sub( camera.position ).dot( _axis );
39
+ target.copy( camera.position ).addScaledVector( _axis, dist );
40
+ return target;
41
+
42
+ }
43
+
44
+ // Renders the portal with an orthographic camera
45
+ function RenderPortal( props ) {
46
+
47
+ const { defaultScene, defaultCamera, overrideRenderLoop = true, renderPriority = 1 } = props;
48
+ const camera = useMemo( () => new OrthographicCamera(), [] );
49
+ const [ set, size, gl, scene ] = useThree( state => [ state.set, state.size, state.gl, state.scene ] );
50
+ useEffect( () => {
51
+
52
+ set( { camera } );
53
+
54
+ }, [ set, camera ] );
55
+
56
+ useEffect( () => {
57
+
58
+ camera.left = - size.width / 2;
59
+ camera.right = size.width / 2;
60
+ camera.top = size.height / 2;
61
+ camera.bottom = - size.height / 2;
62
+ camera.near = 0;
63
+ camera.far = 2000;
64
+ camera.position.z = camera.far / 2;
65
+ camera.updateProjectionMatrix();
66
+
67
+ }, [ camera, size ] );
68
+
69
+ useFrame( () => {
70
+
71
+ if ( overrideRenderLoop ) {
72
+
73
+ gl.render( defaultScene, defaultCamera );
74
+
75
+ }
76
+
77
+ const currentAutoClear = gl.autoClear;
78
+ gl.autoClear = false;
79
+
80
+ gl.clearDepth();
81
+ gl.render( scene, camera );
82
+
83
+ gl.autoClear = currentAutoClear;
84
+
85
+ }, renderPriority );
86
+
87
+ }
88
+
89
+ // generates an extruded box geometry
90
+ function TriangleGeometry() {
91
+
92
+ const ref = useRef();
93
+ useEffect( () => {
94
+
95
+ const geometry = ref.current;
96
+ const position = geometry.attributes.position;
97
+ for ( let i = 0, l = position.count; i < l; i ++ ) {
98
+
99
+ _vec.fromBufferAttribute( position, i );
100
+ if ( _vec.y > 0 ) {
101
+
102
+ _vec.x = 0;
103
+ position.setXYZ( i, ..._vec );
104
+
105
+ }
106
+
107
+ }
108
+
109
+ } );
110
+
111
+ return <boxGeometry ref={ ref } />;
112
+
113
+ }
114
+
115
+ // renders a typical compass graphic with red north triangle, white south, and a tinted circular background
116
+ function CompassGraphic( { northColor = 0xEF5350, southColor = 0xFFFFFF } ) {
117
+
118
+ const [ lightTarget, setLightTarget ] = useState();
119
+ const groupRef = useRef();
120
+ useEffect( () => {
121
+
122
+ setLightTarget( groupRef.current );
123
+
124
+ }, [] );
125
+
126
+ return (
127
+ <group scale={ 0.5 } ref={ groupRef }>
128
+
129
+ {/* Lights */}
130
+ <ambientLight intensity={ 1 } />
131
+ <directionalLight position={ [ 0, 2, 3 ] } intensity={ 3 } target={ lightTarget } />
132
+ <directionalLight position={ [ 0, - 2, - 3 ] } intensity={ 3 } target={ lightTarget } />
133
+
134
+ {/* Background */}
135
+ <mesh>
136
+ <sphereGeometry />
137
+ <meshBasicMaterial color={ 0 } opacity={ 0.3 } transparent={ true } side={ BackSide } />
138
+ </mesh>
139
+
140
+ {/* Compass shape */}
141
+ <group scale={ [ 0.5, 1, 0.15 ] }>
142
+ <mesh position-y={ 0.5 }>
143
+ <TriangleGeometry />
144
+ <meshStandardMaterial color={ northColor } />
145
+ </mesh>
146
+ <mesh position-y={ - 0.5 } rotation-x={ Math.PI }>
147
+ <TriangleGeometry />
148
+ <meshStandardMaterial color={ southColor } />
149
+ </mesh>
150
+ </group>
151
+ </group>
152
+ );
153
+
154
+ }
155
+
156
+ export function CompassGizmo( { children, overrideRenderLoop, mode = '3d', margin = 10, scale = 35, visible = true, ...rest } ) {
157
+
158
+ const [ defaultCamera, defaultScene, size ] = useThree( state => [ state.camera, state.scene, state.size ] );
159
+ const tiles = useContext( TilesRendererContext );
160
+ const groupRef = useRef( null );
161
+ const scene = useMemo( () => {
162
+
163
+ return new Scene();
164
+
165
+ }, [] );
166
+
167
+ useFrame( () => {
168
+
169
+ if ( tiles === null || groupRef.current === null ) {
170
+
171
+ return null;
172
+
173
+ }
174
+
175
+ const { ellipsoid } = tiles;
176
+ const group = groupRef.current;
177
+
178
+ // get the ENU frame in world space
179
+ _matrix.copy( tiles.group.matrixWorld ).invert();
180
+ getCameraFocusPoint( defaultCamera, ellipsoid, tiles.group, _pos ).applyMatrix4( _matrix );
181
+ ellipsoid.getPositionToCartographic( _pos, _cart );
182
+
183
+ ellipsoid
184
+ .getRotationMatrixFromAzElRoll( _cart.lat, _cart.lon, 0, 0, 0, _enuMatrix )
185
+ .premultiply( tiles.group.matrixWorld );
186
+
187
+ // get the camera orientation in the local ENU frame
188
+ _enuMatrix.invert();
189
+ _matrix.copy( defaultCamera.matrixWorld ).premultiply( _enuMatrix );
190
+
191
+ if ( mode.toLowerCase() === '3d' ) {
192
+
193
+ group.quaternion.setFromRotationMatrix( _matrix ).invert();
194
+
195
+ } else {
196
+
197
+ // get the projected facing direction of the camera
198
+ _vec.set( 0, 1, 0 ).transformDirection( _matrix ).normalize();
199
+ _vec.z = 0;
200
+ _vec.normalize();
201
+
202
+ if ( _vec.length() === 0 ) {
203
+
204
+ // if we're looking exactly top-down
205
+ group.quaternion.identity();
206
+
207
+ } else {
208
+
209
+ // compute the 2d looking direction
210
+ const angle = _axis.set( 0, 1, 0 ).angleTo( _vec );
211
+ _axis.cross( _vec ).normalize();
212
+ group.quaternion.setFromAxisAngle( _axis, - angle );
213
+
214
+ }
215
+
216
+ }
217
+
218
+ } );
219
+
220
+ // default to the compass graphic
221
+ if ( ! children ) {
222
+
223
+ children = <CompassGraphic />;
224
+
225
+ }
226
+
227
+ // remove the portal rendering if not present
228
+ if ( ! visible ) {
229
+
230
+ return null;
231
+
232
+ }
233
+
234
+ return (
235
+ createPortal(
236
+ <>
237
+ <group
238
+ ref={ groupRef }
239
+ scale={ scale }
240
+ position={ [
241
+ size.width / 2 - margin - scale / 2,
242
+ - size.height / 2 + margin + scale / 2,
243
+ 0,
244
+ ] }
245
+
246
+ { ...rest }
247
+ >{ children }</group>
248
+ <RenderPortal
249
+ defaultCamera={ defaultCamera }
250
+ defaultScene={ defaultScene }
251
+ overrideRenderLoop={ overrideRenderLoop }
252
+ renderPriority={ 10 }
253
+ />
254
+ </>,
255
+ scene,
256
+ { events: { priority: 10 } },
257
+ )
258
+ );
259
+
260
+ }
@@ -0,0 +1,110 @@
1
+ import { useContext, useState, useEffect, useMemo } from 'react';
2
+ import { TilesRendererContext } from './TilesRenderer.jsx';
3
+ import { CanvasDOMOverlay } from './CanvasDOMOverlay.jsx';
4
+
5
+ // Overlay for displaying tile data set attributions
6
+ export function TilesAttributionOverlay( { children, style, ...rest } ) {
7
+
8
+ const tiles = useContext( TilesRendererContext );
9
+ const [ attributions, setAttributions ] = useState( [] );
10
+
11
+ // Add events for checking when attributions may be updated
12
+ useEffect( () => {
13
+
14
+ if ( ! tiles ) {
15
+
16
+ return;
17
+
18
+ }
19
+
20
+ let queued = false;
21
+ const callback = () => {
22
+
23
+ if ( ! queued ) {
24
+
25
+ queued = true;
26
+ queueMicrotask( () => {
27
+
28
+ setAttributions( tiles.getAttributions() );
29
+ queued = false;
30
+
31
+ } );
32
+
33
+ }
34
+
35
+ };
36
+
37
+ tiles.addEventListener( 'tile-visibility-change', callback );
38
+ tiles.addEventListener( 'load-tile-set', callback );
39
+
40
+ return () => {
41
+
42
+ tiles.removeEventListener( 'tile-visibility-change', callback );
43
+ tiles.removeEventListener( 'load-tile-set', callback );
44
+
45
+ };
46
+
47
+ }, [ tiles ] );
48
+
49
+ // generate elements for each type of attribution
50
+ const output = [];
51
+ attributions.forEach( ( att, i ) => {
52
+
53
+ let element = null;
54
+ if ( att.type === 'string' ) {
55
+
56
+ element = <div key={ i }>{ att.value }</div>;
57
+
58
+ } else if ( att.type === 'html' ) {
59
+
60
+ element = <div key={ i } dangerouslySetInnerHTML={ { __html: att.value } } style={ { pointerEvents: 'all' } }/>;
61
+
62
+ } else if ( att.type === 'image' ) {
63
+
64
+ element = <div key={ i }><img src={ att.value } /></div>;
65
+
66
+ }
67
+
68
+ if ( element ) {
69
+
70
+ output.push( element );
71
+
72
+ }
73
+
74
+ } );
75
+
76
+ // Generate CSS for modifying child elements implicit to the html attributions
77
+ const classId = useMemo( () => 'class_' + window.crypto.randomUUID(), [] );
78
+ const styles = useMemo( () => `
79
+ #${ classId } a {
80
+ color: white;
81
+ }
82
+
83
+ #${ classId } img {
84
+ max-width: 125px;
85
+ display: block;
86
+ margin: 5px 0;
87
+ }
88
+ `, [ classId ] );
89
+
90
+ return (
91
+ <CanvasDOMOverlay
92
+ id={ classId }
93
+ style={ {
94
+ position: 'absolute',
95
+ bottom: 0,
96
+ left: 0,
97
+ padding: '10px',
98
+ color: 'rgba( 255, 255, 255, 0.75 )',
99
+ fontSize: '10px',
100
+ ...style,
101
+ } }
102
+ { ...rest }
103
+ >
104
+ <style>{ styles }</style>
105
+ { children }
106
+ { output }
107
+ </CanvasDOMOverlay>
108
+ );
109
+
110
+ }