itowns 2.45.1-next.0 → 2.45.1-next.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 (185) hide show
  1. package/dist/455.js +2 -0
  2. package/dist/455.js.map +1 -0
  3. package/dist/debug.js +3 -0
  4. package/dist/debug.js.LICENSE.txt +13 -0
  5. package/dist/debug.js.map +1 -0
  6. package/dist/itowns.js +3 -0
  7. package/dist/itowns.js.LICENSE.txt +5 -0
  8. package/dist/itowns.js.map +1 -0
  9. package/dist/itowns_lasparser.js +2 -0
  10. package/dist/itowns_lasparser.js.map +1 -0
  11. package/dist/itowns_lasworker.js +2 -0
  12. package/dist/itowns_lasworker.js.map +1 -0
  13. package/dist/itowns_potree2worker.js +2 -0
  14. package/dist/itowns_potree2worker.js.map +1 -0
  15. package/dist/itowns_widgets.js +2 -0
  16. package/dist/itowns_widgets.js.map +1 -0
  17. package/lib/Controls/FirstPersonControls.js +308 -0
  18. package/lib/Controls/FlyControls.js +175 -0
  19. package/lib/Controls/GlobeControls.js +1178 -0
  20. package/lib/Controls/PlanarControls.js +1025 -0
  21. package/lib/Controls/StateControl.js +432 -0
  22. package/lib/Controls/StreetControls.js +392 -0
  23. package/lib/Converter/Feature2Mesh.js +612 -0
  24. package/lib/Converter/Feature2Texture.js +174 -0
  25. package/lib/Converter/convertToTile.js +70 -0
  26. package/lib/Converter/textureConverter.js +43 -0
  27. package/lib/Core/3DTiles/C3DTBatchTable.js +131 -0
  28. package/lib/Core/3DTiles/C3DTBatchTableHierarchyExtension.js +96 -0
  29. package/lib/Core/3DTiles/C3DTBoundingVolume.js +156 -0
  30. package/lib/Core/3DTiles/C3DTExtensions.js +97 -0
  31. package/lib/Core/3DTiles/C3DTFeature.js +110 -0
  32. package/lib/Core/3DTiles/C3DTilesEnums.js +20 -0
  33. package/lib/Core/3DTiles/C3DTileset.js +99 -0
  34. package/lib/Core/3DTiles/utils/BinaryPropertyAccessor.js +100 -0
  35. package/lib/Core/AnimationPlayer.js +142 -0
  36. package/lib/Core/CopcNode.js +174 -0
  37. package/lib/Core/Deprecated/Undeprecator.js +74 -0
  38. package/lib/Core/EntwinePointTileNode.js +126 -0
  39. package/lib/Core/Feature.js +488 -0
  40. package/lib/Core/Geographic/GeoidGrid.js +108 -0
  41. package/lib/Core/Label.js +222 -0
  42. package/lib/Core/MainLoop.js +209 -0
  43. package/lib/Core/Picking.js +255 -0
  44. package/lib/Core/PointCloudNode.js +42 -0
  45. package/lib/Core/Potree2Node.js +206 -0
  46. package/lib/Core/Potree2PointAttributes.js +139 -0
  47. package/lib/Core/PotreeNode.js +101 -0
  48. package/lib/Core/Prefab/Globe/Atmosphere.js +293 -0
  49. package/lib/Core/Prefab/Globe/GlobeLayer.js +152 -0
  50. package/lib/Core/Prefab/Globe/GlobeTileBuilder.js +110 -0
  51. package/lib/Core/Prefab/Globe/SkyShader.js +78 -0
  52. package/lib/Core/Prefab/GlobeView.js +155 -0
  53. package/lib/Core/Prefab/Planar/PlanarLayer.js +59 -0
  54. package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +71 -0
  55. package/lib/Core/Prefab/PlanarView.js +62 -0
  56. package/lib/Core/Prefab/TileBuilder.js +82 -0
  57. package/lib/Core/Prefab/computeBufferTileGeometry.js +248 -0
  58. package/lib/Core/Scheduler/Cache.js +17 -0
  59. package/lib/Core/Scheduler/CancelledCommandException.js +15 -0
  60. package/lib/Core/Scheduler/Scheduler.js +294 -0
  61. package/lib/Core/Style.js +660 -0
  62. package/lib/Core/StyleOptions.js +486 -0
  63. package/lib/Core/System/Capabilities.js +63 -0
  64. package/lib/Core/Tile/Tile.js +205 -0
  65. package/lib/Core/Tile/TileGrid.js +49 -0
  66. package/lib/Core/TileGeometry.js +124 -0
  67. package/lib/Core/TileMesh.js +108 -0
  68. package/lib/Core/View.js +1115 -0
  69. package/lib/Layer/C3DTilesLayer.js +459 -0
  70. package/lib/Layer/ColorLayer.js +154 -0
  71. package/lib/Layer/CopcLayer.js +63 -0
  72. package/lib/Layer/ElevationLayer.js +139 -0
  73. package/lib/Layer/EntwinePointTileLayer.js +71 -0
  74. package/lib/Layer/FeatureGeometryLayer.js +77 -0
  75. package/lib/Layer/GeoidLayer.js +80 -0
  76. package/lib/Layer/GeometryLayer.js +233 -0
  77. package/lib/Layer/InfoLayer.js +64 -0
  78. package/lib/Layer/LabelLayer.js +469 -0
  79. package/lib/Layer/Layer.js +335 -0
  80. package/lib/Layer/LayerUpdateState.js +89 -0
  81. package/lib/Layer/LayerUpdateStrategy.js +80 -0
  82. package/lib/Layer/OGC3DTilesLayer.js +543 -0
  83. package/lib/Layer/OrientedImageLayer.js +227 -0
  84. package/lib/Layer/PointCloudLayer.js +405 -0
  85. package/lib/Layer/Potree2Layer.js +171 -0
  86. package/lib/Layer/PotreeLayer.js +72 -0
  87. package/lib/Layer/RasterLayer.js +37 -0
  88. package/lib/Layer/ReferencingLayerProperties.js +62 -0
  89. package/lib/Layer/TiledGeometryLayer.js +459 -0
  90. package/lib/Loader/LASLoader.js +193 -0
  91. package/lib/Loader/Potree2BrotliLoader.js +261 -0
  92. package/lib/Loader/Potree2Loader.js +207 -0
  93. package/lib/Main.js +113 -0
  94. package/lib/MainBundle.js +4 -0
  95. package/lib/Parser/B3dmParser.js +174 -0
  96. package/lib/Parser/CameraCalibrationParser.js +94 -0
  97. package/lib/Parser/GDFParser.js +72 -0
  98. package/lib/Parser/GTXParser.js +75 -0
  99. package/lib/Parser/GeoJsonParser.js +212 -0
  100. package/lib/Parser/GpxParser.js +25 -0
  101. package/lib/Parser/ISGParser.js +71 -0
  102. package/lib/Parser/KMLParser.js +25 -0
  103. package/lib/Parser/LASParser.js +137 -0
  104. package/lib/Parser/MapBoxUrlParser.js +83 -0
  105. package/lib/Parser/PntsParser.js +131 -0
  106. package/lib/Parser/Potree2BinParser.js +92 -0
  107. package/lib/Parser/PotreeBinParser.js +106 -0
  108. package/lib/Parser/PotreeCinParser.js +29 -0
  109. package/lib/Parser/ShapefileParser.js +78 -0
  110. package/lib/Parser/VectorTileParser.js +215 -0
  111. package/lib/Parser/XbilParser.js +120 -0
  112. package/lib/Parser/deprecated/LegacyGLTFLoader.js +1386 -0
  113. package/lib/Parser/iGLTFLoader.js +168 -0
  114. package/lib/Process/3dTilesProcessing.js +304 -0
  115. package/lib/Process/FeatureProcessing.js +76 -0
  116. package/lib/Process/LayeredMaterialNodeProcessing.js +229 -0
  117. package/lib/Process/ObjectRemovalHelper.js +97 -0
  118. package/lib/Process/handlerNodeError.js +23 -0
  119. package/lib/Provider/3dTilesProvider.js +149 -0
  120. package/lib/Provider/DataSourceProvider.js +24 -0
  121. package/lib/Provider/Fetcher.js +233 -0
  122. package/lib/Provider/PointCloudProvider.js +45 -0
  123. package/lib/Provider/TileProvider.js +16 -0
  124. package/lib/Provider/URLBuilder.js +116 -0
  125. package/lib/Renderer/Camera.js +281 -0
  126. package/lib/Renderer/Color.js +56 -0
  127. package/lib/Renderer/ColorLayersOrdering.js +115 -0
  128. package/lib/Renderer/CommonMaterial.js +31 -0
  129. package/lib/Renderer/Label2DRenderer.js +192 -0
  130. package/lib/Renderer/LayeredMaterial.js +243 -0
  131. package/lib/Renderer/OBB.js +150 -0
  132. package/lib/Renderer/OrientedImageCamera.js +118 -0
  133. package/lib/Renderer/OrientedImageMaterial.js +167 -0
  134. package/lib/Renderer/PointsMaterial.js +485 -0
  135. package/lib/Renderer/RasterTile.js +243 -0
  136. package/lib/Renderer/RenderMode.js +31 -0
  137. package/lib/Renderer/Shader/ShaderChunk.js +160 -0
  138. package/lib/Renderer/Shader/ShaderUtils.js +47 -0
  139. package/lib/Renderer/SphereHelper.js +17 -0
  140. package/lib/Renderer/WebXR.js +51 -0
  141. package/lib/Renderer/c3DEngine.js +214 -0
  142. package/lib/Source/C3DTilesGoogleSource.js +74 -0
  143. package/lib/Source/C3DTilesIonSource.js +54 -0
  144. package/lib/Source/C3DTilesSource.js +30 -0
  145. package/lib/Source/CopcSource.js +126 -0
  146. package/lib/Source/EntwinePointTileSource.js +72 -0
  147. package/lib/Source/FileSource.js +188 -0
  148. package/lib/Source/OGC3DTilesGoogleSource.js +29 -0
  149. package/lib/Source/OGC3DTilesIonSource.js +34 -0
  150. package/lib/Source/OGC3DTilesSource.js +21 -0
  151. package/lib/Source/OrientedImageSource.js +59 -0
  152. package/lib/Source/Potree2Source.js +167 -0
  153. package/lib/Source/PotreeSource.js +82 -0
  154. package/lib/Source/Source.js +202 -0
  155. package/lib/Source/TMSSource.js +144 -0
  156. package/lib/Source/VectorTilesSource.js +182 -0
  157. package/lib/Source/WFSSource.js +170 -0
  158. package/lib/Source/WMSSource.js +167 -0
  159. package/lib/Source/WMTSSource.js +92 -0
  160. package/lib/ThreeExtended/capabilities/WebGL.js +69 -0
  161. package/lib/ThreeExtended/libs/ktx-parse.module.js +506 -0
  162. package/lib/ThreeExtended/libs/zstddec.module.js +29 -0
  163. package/lib/ThreeExtended/loaders/DDSLoader.js +200 -0
  164. package/lib/ThreeExtended/loaders/DRACOLoader.js +400 -0
  165. package/lib/ThreeExtended/loaders/GLTFLoader.js +2879 -0
  166. package/lib/ThreeExtended/loaders/KTX2Loader.js +709 -0
  167. package/lib/ThreeExtended/math/ColorSpaces.js +59 -0
  168. package/lib/ThreeExtended/utils/BufferGeometryUtils.js +846 -0
  169. package/lib/ThreeExtended/utils/WorkerPool.js +70 -0
  170. package/lib/Utils/CameraUtils.js +554 -0
  171. package/lib/Utils/DEMUtils.js +350 -0
  172. package/lib/Utils/FeaturesUtils.js +156 -0
  173. package/lib/Utils/Gradients.js +16 -0
  174. package/lib/Utils/ThreeUtils.js +115 -0
  175. package/lib/Utils/gui/C3DTilesStyle.js +218 -0
  176. package/lib/Utils/gui/Main.js +7 -0
  177. package/lib/Utils/gui/Minimap.js +152 -0
  178. package/lib/Utils/gui/Navigation.js +245 -0
  179. package/lib/Utils/gui/Scale.js +104 -0
  180. package/lib/Utils/gui/Searchbar.js +234 -0
  181. package/lib/Utils/gui/Widget.js +80 -0
  182. package/lib/Utils/placeObjectOnGround.js +136 -0
  183. package/lib/Worker/LASLoaderWorker.js +19 -0
  184. package/lib/Worker/Potree2Worker.js +21 -0
  185. package/package.json +2 -2
@@ -0,0 +1,168 @@
1
+ import * as THREE from 'three';
2
+ import LegacyGLTFLoader from "./deprecated/LegacyGLTFLoader.js";
3
+ import { GLTFLoader } from "../ThreeExtended/loaders/GLTFLoader.js";
4
+ class iGLTFLoader extends THREE.Loader {
5
+ /**
6
+ * Parses [glTF](https://www.khronos.org/gltf/) 1.0 and 2.0 files.
7
+ *
8
+ * Under the hood, glTF 2.0 files are parsed with THREE.GLTFLoader and GLTF 1.0 are parsed with the previous THREE
9
+ * GltfLoader (for 1.0 glTF) that has been kept and maintained in iTowns.
10
+ *
11
+ * Beware that gltf convention is y-up while itowns is z-up. You can apply a PI/2 rotation around the X axis to the
12
+ * loaded model to transform from y-up to z-up. Note that you can also use Coordinates.geodesicNormal to get the normal
13
+ * to a position on the globe (i.e. in GlobeView) to correctly orient a model on a GlobeView.
14
+ *
15
+ * @param {THREE.LoadingManager} [manager] - The loadingManager for the loader to use. Default is THREE.DefaultLoadingManager.
16
+ */
17
+ constructor(manager) {
18
+ super(manager);
19
+ this.legacyGLTFLoader = new LegacyGLTFLoader();
20
+ this.glTFLoader = new GLTFLoader();
21
+ }
22
+
23
+ /**
24
+ * Loads a gltf model from url and call the callback function with the parsed response content.
25
+ * Adapted from threejs.
26
+ * @param {String} url - the path/URL of the .gltf or .glb file.
27
+ * @param {Function} onLoad - A function to be called after the loading is successfully completed. The function
28
+ * receives the loaded JSON response returned from {@link parse}.
29
+ * @param {Function} onProgress
30
+ * @param {Function} onError
31
+ */
32
+ load(url, onLoad, onProgress, onError) {
33
+ const scope = this;
34
+ let resourcePath;
35
+ if (this.resourcePath !== '') {
36
+ resourcePath = this.resourcePath;
37
+ } else if (this.path !== '') {
38
+ // If a base path is set, resources will be relative paths from that plus the relative path of the gltf file
39
+ // Example path = 'https://my-cnd-server.com/', url = 'assets/models/model.gltf'
40
+ // resourcePath = 'https://my-cnd-server.com/assets/models/'
41
+ // referenced resource 'model.bin' will be loaded from 'https://my-cnd-server.com/assets/models/model.bin'
42
+ // referenced resource '../textures/texture.png' will be loaded from 'https://my-cnd-server.com/assets/textures/texture.png'
43
+ const relativeUrl = THREE.LoaderUtils.extractUrlBase(url);
44
+ resourcePath = THREE.LoaderUtils.resolveURL(relativeUrl, this.path);
45
+ } else {
46
+ resourcePath = THREE.LoaderUtils.extractUrlBase(url);
47
+ }
48
+
49
+ // Tells the LoadingManager to track an extra item, which resolves after
50
+ // the model is fully loaded. This means the count of items loaded will
51
+ // be incorrect, but ensures manager.onLoad() does not fire early.
52
+ this.manager.itemStart(url);
53
+ const _onError = e => {
54
+ if (onError) {
55
+ onError(e);
56
+ } else {
57
+ console.error(e);
58
+ }
59
+ scope.manager.itemError(url);
60
+ scope.manager.itemEnd(url);
61
+ };
62
+ const loader = new THREE.FileLoader(this.manager);
63
+ loader.setPath(this.path);
64
+ loader.setResponseType('arraybuffer');
65
+ loader.setRequestHeader(this.requestHeader);
66
+ loader.setWithCredentials(this.withCredentials);
67
+ loader.load(url, data => {
68
+ try {
69
+ scope.parse(data, resourcePath, gltf => {
70
+ onLoad(gltf);
71
+ scope.manager.itemEnd(url);
72
+ }, _onError);
73
+ } catch (e) {
74
+ _onError(e);
75
+ }
76
+ }, onProgress, _onError);
77
+ }
78
+
79
+ /**
80
+ * Sets the draco loader instance for this gltf parser. Enable loading files with
81
+ * [Draco](https://google.github.io/draco/) geometry extension. See Threejs
82
+ * [DracoLoader](https://threejs.org/docs/index.html#examples/en/loaders/DRACOLoader) for more information.
83
+ * Only works for GLTF 2.0 files.
84
+ * @param {THREE.DracoLoader} dracoLoader - the threejs DracoLoader instance.
85
+ */
86
+ setDRACOLoader(dracoLoader) {
87
+ this.glTFLoader.setDRACOLoader(dracoLoader);
88
+ }
89
+
90
+ /**
91
+ * Sets the KTX2 loader instance for this gltf parser. Enable loading files with
92
+ * [KTX2](https://www.khronos.org/ktx/) texture extension. See Threejs
93
+ * [KTX2Loader](https://threejs.org/docs/index.html?q=KTX2#examples/en/loaders/KTX2Loader) for more information.
94
+ * Only works for GLTF 2.0 files.
95
+ * @param {THREE.KTX2Loader} ktx2Loader - the threejs KTX2Loader instance.
96
+ */
97
+ setKTX2Loader(ktx2Loader) {
98
+ this.glTFLoader.setKTX2Loader(ktx2Loader);
99
+ }
100
+
101
+ /**
102
+ * Sets the Mesh Optimizer decoder instance for this gltf parser. Enable loading files with
103
+ * [MeshOptimizer](https://meshoptimizer.org/) geometry extension.
104
+ * Only works for GLTF 2.0 files.
105
+ * @param {Object} meshoptDecoder - the threejs meshopt decoder instance.
106
+ */
107
+ setMeshoptDecoder(meshoptDecoder) {
108
+ this.glTFLoader.setMeshoptDecoder(meshoptDecoder);
109
+ }
110
+
111
+ /**
112
+ * Registers a callback to load specific unknown or not standard GLTF extensions.
113
+ * See Threejs [GltfLoader](https://threejs.org/docs/?q=gltflo#examples/en/loaders/GLTFLoader) for more
114
+ * information.
115
+ * @param {Function} callback - the callback function
116
+ */
117
+ register(callback) {
118
+ this.glTFLoader.register(callback);
119
+ }
120
+
121
+ /**
122
+ * Unregisters a load callback.
123
+ * See Threejs [GltfLoader](https://threejs.org/docs/?q=gltflo#examples/en/loaders/GLTFLoader) for more
124
+ * information.
125
+ * @param {Function} callback - the callback function
126
+ */
127
+ unregister(callback) {
128
+ this.glTFLoader.unregister(callback);
129
+ }
130
+
131
+ /** Parse a glTF-based ArrayBuffer, JSON string or object and fire onLoad callback when complete.
132
+ * Calls Threejs [GLTFLoader.parse](https://threejs.org/docs/?q=gltflo#examples/en/loaders/GLTFLoader.parse) for
133
+ * glTF 2.0 files and LegacyGLTFLoader.parse for gtTF 1.0 files.
134
+ * @param {ArrayBuffer|String|Object} buffer - the glTF asset to parse, as an ArrayBuffer, JSON string or object.
135
+ * @param {String} path - the base path from which to find subsequent glTF resources such as textures and .bin data files.
136
+ * @param {Function} onLoad — A function to be called when parse completes. The argument to the onLoad function will
137
+ * be an Object that contains loaded parts: .scene, .scenes, .cameras, .animations, and .asset.
138
+ * @param {Function} [onError] — A function to be called if an error occurs during parsing. The function receives error as an argument.
139
+ */
140
+ parse(buffer, path, onLoad, onError) {
141
+ if (!buffer || !path) {
142
+ onError('[iGLTFLoader]: Buffer and path are mandatory to parse a glTF.');
143
+ return;
144
+ }
145
+ const headerView = new DataView(buffer, 0, 20);
146
+ const version = headerView.getUint32(4, true);
147
+ if (version === 1) {
148
+ this.legacyGLTFLoader.parse(buffer, path, onLoad, onError);
149
+ } else {
150
+ this.glTFLoader.parse(buffer, path, onLoad, onError);
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Async promise-based parsing of a glTF-based ArrayBuffer, JSON string or object.
156
+ * @param {ArrayBuffer|String|Object} data - the glTF asset to parse, as an ArrayBuffer, JSON string or object.
157
+ * @param {String} path - the base path from which to find subsequent glTF resources such as textures and .bin data files.
158
+ * @returns {Promise<Object>} A promise that resolves an Object that contains loaded parts:
159
+ * .scene, .scenes, .cameras, .animations, and .asset, when parsing is done.
160
+ */
161
+ parseAsync(data, path) {
162
+ const scope = this;
163
+ return new Promise((resolve, reject) => {
164
+ scope.parse(data, path, resolve, reject);
165
+ });
166
+ }
167
+ }
168
+ export default iGLTFLoader;
@@ -0,0 +1,304 @@
1
+ import * as THREE from 'three';
2
+ import ObjectRemovalHelper from "./ObjectRemovalHelper.js";
3
+ import { C3DTilesBoundingVolumeTypes } from "../Core/3DTiles/C3DTilesEnums.js";
4
+ import { C3DTILES_LAYER_EVENTS } from "../Layer/C3DTilesLayer.js";
5
+
6
+ /** @module 3dTilesProcessing
7
+ */
8
+
9
+ function requestNewTile(view, scheduler, geometryLayer, metadata, parent, redraw) {
10
+ const command = {
11
+ /* mandatory */
12
+ view,
13
+ requester: parent,
14
+ layer: geometryLayer,
15
+ priority: parent ? 1.0 / (parent.distance + 1) : 100,
16
+ /* specific params */
17
+ metadata,
18
+ redraw
19
+ };
20
+ geometryLayer.dispatchEvent({
21
+ type: C3DTILES_LAYER_EVENTS.ON_TILE_REQUESTED,
22
+ metadata
23
+ });
24
+ return scheduler.execute(command);
25
+ }
26
+ function getChildTiles(tile) {
27
+ // only keep children that have the same layer and a valid tileId
28
+ return tile.children.filter(n => n.layer == tile.layer && n.tileId);
29
+ }
30
+ function subdivideNode(context, layer, node, cullingTest) {
31
+ if (node.additiveRefinement) {
32
+ // Additive refinement can only fetch visible children.
33
+ _subdivideNodeAdditive(context, layer, node, cullingTest);
34
+ } else {
35
+ // Substractive refinement on the other hand requires to replace
36
+ // node with all of its children
37
+ _subdivideNodeSubstractive(context, layer, node);
38
+ }
39
+ }
40
+ const tmpMatrix = new THREE.Matrix4();
41
+ function _subdivideNodeAdditive(context, layer, node, cullingTest) {
42
+ for (const child of layer.tileset.tiles[node.tileId].children) {
43
+ // child being downloaded => skip
44
+ if (child.promise || child.loaded) {
45
+ continue;
46
+ }
47
+
48
+ // 'child' is only metadata (it's *not* a THREE.Object3D). 'cullingTest' needs
49
+ // a matrixWorld, so we compute it: it's node's matrixWorld x child's transform
50
+ let overrideMatrixWorld = node.matrixWorld;
51
+ if (child.transform) {
52
+ overrideMatrixWorld = tmpMatrix.multiplyMatrices(node.matrixWorld, child.transform);
53
+ }
54
+ const isVisible = cullingTest ? !cullingTest(layer, context.camera, child, overrideMatrixWorld) : true;
55
+
56
+ // child is not visible => skip
57
+ if (!isVisible) {
58
+ continue;
59
+ }
60
+ child.promise = requestNewTile(context.view, context.scheduler, layer, child, node, true).then(tile => {
61
+ node.add(tile);
62
+ tile.updateMatrixWorld();
63
+ layer.onTileContentLoaded(tile);
64
+ context.view.notifyChange(child);
65
+ child.loaded = true;
66
+ delete child.promise;
67
+ });
68
+ }
69
+ }
70
+ function _subdivideNodeSubstractive(context, layer, node) {
71
+ if (!node.pendingSubdivision && getChildTiles(node).length == 0) {
72
+ const childrenTiles = layer.tileset.tiles[node.tileId].children;
73
+ if (childrenTiles === undefined || childrenTiles.length === 0) {
74
+ return;
75
+ }
76
+ node.pendingSubdivision = true;
77
+ const promises = [];
78
+ for (let i = 0; i < childrenTiles.length; i++) {
79
+ promises.push(requestNewTile(context.view, context.scheduler, layer, childrenTiles[i], node, false).then(tile => {
80
+ childrenTiles[i].loaded = true;
81
+ node.add(tile);
82
+ tile.updateMatrixWorld();
83
+ // TODO: remove because cannot happen?
84
+ if (node.additiveRefinement) {
85
+ context.view.notifyChange(node);
86
+ }
87
+ layer.tileset.tiles[tile.tileId].loaded = true;
88
+ layer.onTileContentLoaded(tile);
89
+ }));
90
+ }
91
+ Promise.all(promises).then(() => {
92
+ node.pendingSubdivision = false;
93
+ context.view.notifyChange(node);
94
+ });
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Check if the node is visible in the camera.
100
+ *
101
+ * @param {C3DTilesLayer} layer node 3D tiles layer
102
+ * @param {Camera} camera camera
103
+ * @param {THREE.Object3D} node The 3d tile node to check.
104
+ * @param {THREE.Matrix4} tileMatrixWorld The node matrix world
105
+ * @return {boolean} return true if the node is visible
106
+ */
107
+ export function $3dTilesCulling(layer, camera, node, tileMatrixWorld) {
108
+ // For viewer Request Volume
109
+ // https://github.com/AnalyticalGraphicsInc/3d-tiles-samples/tree/master/tilesets/TilesetWithRequestVolume
110
+ if (node.viewerRequestVolume && node.viewerRequestVolume.viewerRequestVolumeCulling(camera, tileMatrixWorld)) {
111
+ return true;
112
+ }
113
+
114
+ // For bounding volume
115
+ return !!(node.boundingVolume && node.boundingVolume.boundingVolumeCulling(camera, tileMatrixWorld));
116
+ }
117
+
118
+ // Cleanup all 3dtiles|three.js starting from a given node n.
119
+ // n's children can be of 2 types:
120
+ // - have a 'content' attribute -> it's a tileset and must
121
+ // be cleaned with cleanup3dTileset()
122
+ // - doesn't have 'content' -> it's a raw Object3D object,
123
+ // and must be cleaned with _cleanupObject3D()
124
+ function cleanup3dTileset(layer, n) {
125
+ let depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
126
+ // If this layer is not using additive refinement, we can only
127
+ // clean a tile if all its neighbours are cleaned as well because
128
+ // a tile can only be in 2 states:
129
+ // - displayed and no children displayed
130
+ // - hidden and all of its children displayed
131
+ // So here we implement a conservative measure: if T is cleanable
132
+ // we actually only clean its children tiles.
133
+ const canCleanCompletely = n.additiveRefinement || depth > 0;
134
+ for (let i = 0; i < n.children.length; i++) {
135
+ // skip non-tiles elements
136
+ if (!n.children[i].content) {
137
+ if (canCleanCompletely) {
138
+ ObjectRemovalHelper.removeChildrenAndCleanupRecursively(n.children[i].layer, n.children[i]);
139
+ }
140
+ } else {
141
+ cleanup3dTileset(layer, n.children[i], depth + 1);
142
+ }
143
+ }
144
+ if (canCleanCompletely) {
145
+ if (n.dispose) {
146
+ n.dispose();
147
+ }
148
+ delete n.content;
149
+ layer.tileset.tiles[n.tileId].loaded = false;
150
+ n.remove(...n.children);
151
+
152
+ // and finally remove from parent
153
+ if (depth == 0 && n.parent) {
154
+ n.parent.remove(n);
155
+ }
156
+ } else {
157
+ const tiles = getChildTiles(n);
158
+ n.remove(...tiles);
159
+ }
160
+ }
161
+
162
+ // this is a layer
163
+ export function pre3dTilesUpdate(context) {
164
+ if (!this.visible) {
165
+ return [];
166
+ }
167
+ this.scale = context.camera._preSSE;
168
+
169
+ // Elements removed are added in the layer._cleanableTiles list.
170
+ // Since we simply push in this array, the first item is always
171
+ // the oldest one.
172
+ const now = Date.now();
173
+ if (this._cleanableTiles.length && now - this._cleanableTiles[0].cleanableSince > this.cleanupDelay) {
174
+ // Make sure we don't clean root tile
175
+ this.root.cleanableSince = undefined;
176
+ let i = 0;
177
+ for (; i < this._cleanableTiles.length; i++) {
178
+ const elt = this._cleanableTiles[i];
179
+ if (now - elt.cleanableSince > this.cleanupDelay) {
180
+ cleanup3dTileset(this, elt);
181
+ } else {
182
+ // later entries are younger
183
+ break;
184
+ }
185
+ }
186
+ // remove deleted elements from _cleanableTiles
187
+ this._cleanableTiles.splice(0, i);
188
+ }
189
+ return [this.root];
190
+ }
191
+ const boundingVolumeBox = new THREE.Box3();
192
+ const boundingVolumeSphere = new THREE.Sphere();
193
+ export function computeNodeSSE(camera, node) {
194
+ node.distance = 0;
195
+ if (node.boundingVolume.initialVolumeType === C3DTilesBoundingVolumeTypes.box) {
196
+ boundingVolumeBox.copy(node.boundingVolume.volume);
197
+ boundingVolumeBox.applyMatrix4(node.matrixWorld);
198
+ node.distance = boundingVolumeBox.distanceToPoint(camera.camera3D.position);
199
+ } else if (node.boundingVolume.initialVolumeType === C3DTilesBoundingVolumeTypes.sphere || node.boundingVolume.initialVolumeType === C3DTilesBoundingVolumeTypes.region) {
200
+ boundingVolumeSphere.copy(node.boundingVolume.volume);
201
+ boundingVolumeSphere.applyMatrix4(node.matrixWorld);
202
+ // TODO: see https://github.com/iTowns/itowns/issues/800
203
+ node.distance = Math.max(0.0, boundingVolumeSphere.distanceToPoint(camera.camera3D.position));
204
+ } else {
205
+ return Infinity;
206
+ }
207
+ if (node.distance === 0) {
208
+ // This test is needed in case geometricError = distance = 0
209
+ return Infinity;
210
+ }
211
+ return camera._preSSE * (node.geometricError / node.distance);
212
+ }
213
+ export function init3dTilesLayer(view, scheduler, layer, rootTile) {
214
+ return requestNewTile(view, scheduler, layer, rootTile, undefined, true).then(tile => {
215
+ layer.object3d.add(tile);
216
+ tile.updateMatrixWorld();
217
+ layer.tileset.tiles[tile.tileId].loaded = true;
218
+ layer.root = tile;
219
+ layer.onTileContentLoaded(tile);
220
+ });
221
+ }
222
+ function setDisplayed(node, display) {
223
+ // The geometry of the tile is not in node, but in node.content
224
+ // To change the display state, we change node.content.visible instead of
225
+ // node.material.visible
226
+ if (node.content) {
227
+ node.content.visible = display;
228
+ }
229
+ }
230
+ function markForDeletion(layer, elt) {
231
+ if (!elt.cleanableSince) {
232
+ elt.cleanableSince = Date.now();
233
+ layer._cleanableTiles.push(elt);
234
+ }
235
+ }
236
+
237
+ /**
238
+ * This funcion builds the method to update 3d tiles node.
239
+ *
240
+ * The returned method checks the 3d tile visibility with `cullingTest` function.
241
+ * It subdivises visible node if `subdivisionTest` return `true`.
242
+ *
243
+ * @param {Function} [cullingTest=$3dTilesCulling] The culling test method.
244
+ * @param {Function} [subdivisionTest=$3dTilesSubdivisionControl] The subdivision test method.
245
+ * @return {Function} { description_of_the_return_value }
246
+ */
247
+ export function process3dTilesNode() {
248
+ let cullingTest = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : $3dTilesCulling;
249
+ let subdivisionTest = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : $3dTilesSubdivisionControl;
250
+ return function (context, layer, node) {
251
+ // early exit if parent's subdivision is in progress
252
+ if (node.parent.pendingSubdivision && !node.parent.additiveRefinement) {
253
+ node.visible = false;
254
+ return undefined;
255
+ }
256
+
257
+ // do proper culling
258
+ const isVisible = cullingTest ? !cullingTest(layer, context.camera, node, node.matrixWorld) : true;
259
+ node.visible = isVisible;
260
+ if (isVisible) {
261
+ if (node.cleanableSince) {
262
+ layer._cleanableTiles.splice(layer._cleanableTiles.indexOf(node), 1);
263
+ node.cleanableSince = undefined;
264
+ }
265
+ let returnValue;
266
+ if (node.pendingSubdivision || subdivisionTest(context, layer, node)) {
267
+ subdivideNode(context, layer, node, cullingTest);
268
+ // display iff children aren't ready
269
+ setDisplayed(node, node.pendingSubdivision || node.additiveRefinement);
270
+ returnValue = getChildTiles(node);
271
+ } else {
272
+ setDisplayed(node, true);
273
+ for (const n of getChildTiles(node)) {
274
+ n.visible = false;
275
+ markForDeletion(layer, n);
276
+ }
277
+ }
278
+ return returnValue;
279
+ }
280
+ markForDeletion(layer, node);
281
+ };
282
+ }
283
+
284
+ /**
285
+ *
286
+ *
287
+ * the method returns true if the `node` should be subivised.
288
+ *
289
+ * @param {object} context The current context
290
+ * @param {Camera} context.camera The current camera
291
+ * @param {C3DTilesLayer} layer The 3d tile layer
292
+ * @param {THREE.Object3D} node The 3d tile node
293
+ * @return {boolean}
294
+ */
295
+ export function $3dTilesSubdivisionControl(context, layer, node) {
296
+ if (layer.tileset.tiles[node.tileId].children === undefined) {
297
+ return false;
298
+ }
299
+ if (layer.tileset.tiles[node.tileId].isTileset) {
300
+ return true;
301
+ }
302
+ const sse = computeNodeSSE(context.camera, node);
303
+ return sse > layer.sseThreshold;
304
+ }
@@ -0,0 +1,76 @@
1
+ import LayerUpdateState from "../Layer/LayerUpdateState.js";
2
+ import ObjectRemovalHelper from "./ObjectRemovalHelper.js";
3
+ import handlingError from "./handlerNodeError.js";
4
+ import { Coordinates } from '@itowns/geographic';
5
+ import { geoidLayerIsVisible } from "../Layer/GeoidLayer.js";
6
+ const coord = new Coordinates('EPSG:4326', 0, 0, 0);
7
+ export default {
8
+ update(context, layer, node) {
9
+ if (!node.parent && node.children.length) {
10
+ // if node has been removed dispose three.js resource
11
+ ObjectRemovalHelper.removeChildrenAndCleanupRecursively(layer, node);
12
+ return;
13
+ }
14
+ if (!node.visible) {
15
+ return;
16
+ }
17
+ if (node.layerUpdateState[layer.id] === undefined) {
18
+ node.layerUpdateState[layer.id] = new LayerUpdateState();
19
+ } else if (!node.layerUpdateState[layer.id].canTryUpdate()) {
20
+ // toggle visibility features
21
+ node.link[layer.id]?.forEach(f => {
22
+ f.layer.object3d.add(f);
23
+ f.meshes.position.z = geoidLayerIsVisible(layer.parent) ? node.geoidHeight : 0;
24
+ f.meshes.updateMatrixWorld();
25
+ });
26
+ return;
27
+ }
28
+ const extentsDestination = node.getExtentsByProjection(layer.source.crs) || [node.extent];
29
+ const zoomDest = extentsDestination[0].zoom;
30
+
31
+ // check if it's tile level is equal to display level layer.
32
+ // TO DO updata at all level asked
33
+ // if ((zoomDest < layer.zoom.min && zoomDest > layer.zoom.max) ||
34
+ if (zoomDest != layer.zoom.min ||
35
+ // check if there's data in extent tile.
36
+ !this.source.extentInsideLimit(node.extent, zoomDest) ||
37
+ // In FileSource case, check if the feature center is in extent tile.
38
+ layer.source.isFileSource && !node.extent.isPointInside(layer.source.extent.center(coord))) {
39
+ // if not, there's not data to add at this tile.
40
+ node.layerUpdateState[layer.id].noMoreUpdatePossible();
41
+ return;
42
+ }
43
+ node.layerUpdateState[layer.id].newTry();
44
+ const command = {
45
+ layer,
46
+ extentsSource: extentsDestination,
47
+ view: context.view,
48
+ requester: node
49
+ };
50
+ return context.scheduler.execute(command).then(featureMeshes => {
51
+ node.layerUpdateState[layer.id].noMoreUpdatePossible();
52
+ featureMeshes.forEach(featureMesh => {
53
+ if (featureMesh) {
54
+ node.link[layer.id] = node.link[layer.id] || [];
55
+ featureMesh.as(context.view.referenceCrs);
56
+ featureMesh.meshes.position.z = geoidLayerIsVisible(layer.parent) ? node.geoidHeight : 0;
57
+ featureMesh.updateMatrixWorld();
58
+ if (layer.onMeshCreated) {
59
+ layer.onMeshCreated(featureMesh, context);
60
+ }
61
+ if (!node.parent) {
62
+ // TODO: Clean cache needs a refactory, because it isn't really efficient and used
63
+ ObjectRemovalHelper.removeChildrenAndCleanupRecursively(layer, featureMesh);
64
+ } else {
65
+ layer.object3d.add(featureMesh);
66
+ node.link[layer.id].push(featureMesh);
67
+ }
68
+ featureMesh.layer = layer;
69
+ } else {
70
+ // TODO: verify if it's possible the featureMesh is undefined.
71
+ node.layerUpdateState[layer.id].failure(1, true);
72
+ }
73
+ });
74
+ }, err => handlingError(err, node, layer, node.level, context.view));
75
+ }
76
+ };