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.
- package/dist/455.js +2 -0
- package/dist/455.js.map +1 -0
- package/dist/debug.js +3 -0
- package/dist/debug.js.LICENSE.txt +13 -0
- package/dist/debug.js.map +1 -0
- package/dist/itowns.js +3 -0
- package/dist/itowns.js.LICENSE.txt +5 -0
- package/dist/itowns.js.map +1 -0
- package/dist/itowns_lasparser.js +2 -0
- package/dist/itowns_lasparser.js.map +1 -0
- package/dist/itowns_lasworker.js +2 -0
- package/dist/itowns_lasworker.js.map +1 -0
- package/dist/itowns_potree2worker.js +2 -0
- package/dist/itowns_potree2worker.js.map +1 -0
- package/dist/itowns_widgets.js +2 -0
- package/dist/itowns_widgets.js.map +1 -0
- package/lib/Controls/FirstPersonControls.js +308 -0
- package/lib/Controls/FlyControls.js +175 -0
- package/lib/Controls/GlobeControls.js +1178 -0
- package/lib/Controls/PlanarControls.js +1025 -0
- package/lib/Controls/StateControl.js +432 -0
- package/lib/Controls/StreetControls.js +392 -0
- package/lib/Converter/Feature2Mesh.js +612 -0
- package/lib/Converter/Feature2Texture.js +174 -0
- package/lib/Converter/convertToTile.js +70 -0
- package/lib/Converter/textureConverter.js +43 -0
- package/lib/Core/3DTiles/C3DTBatchTable.js +131 -0
- package/lib/Core/3DTiles/C3DTBatchTableHierarchyExtension.js +96 -0
- package/lib/Core/3DTiles/C3DTBoundingVolume.js +156 -0
- package/lib/Core/3DTiles/C3DTExtensions.js +97 -0
- package/lib/Core/3DTiles/C3DTFeature.js +110 -0
- package/lib/Core/3DTiles/C3DTilesEnums.js +20 -0
- package/lib/Core/3DTiles/C3DTileset.js +99 -0
- package/lib/Core/3DTiles/utils/BinaryPropertyAccessor.js +100 -0
- package/lib/Core/AnimationPlayer.js +142 -0
- package/lib/Core/CopcNode.js +174 -0
- package/lib/Core/Deprecated/Undeprecator.js +74 -0
- package/lib/Core/EntwinePointTileNode.js +126 -0
- package/lib/Core/Feature.js +488 -0
- package/lib/Core/Geographic/GeoidGrid.js +108 -0
- package/lib/Core/Label.js +222 -0
- package/lib/Core/MainLoop.js +209 -0
- package/lib/Core/Picking.js +255 -0
- package/lib/Core/PointCloudNode.js +42 -0
- package/lib/Core/Potree2Node.js +206 -0
- package/lib/Core/Potree2PointAttributes.js +139 -0
- package/lib/Core/PotreeNode.js +101 -0
- package/lib/Core/Prefab/Globe/Atmosphere.js +293 -0
- package/lib/Core/Prefab/Globe/GlobeLayer.js +152 -0
- package/lib/Core/Prefab/Globe/GlobeTileBuilder.js +110 -0
- package/lib/Core/Prefab/Globe/SkyShader.js +78 -0
- package/lib/Core/Prefab/GlobeView.js +155 -0
- package/lib/Core/Prefab/Planar/PlanarLayer.js +59 -0
- package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +71 -0
- package/lib/Core/Prefab/PlanarView.js +62 -0
- package/lib/Core/Prefab/TileBuilder.js +82 -0
- package/lib/Core/Prefab/computeBufferTileGeometry.js +248 -0
- package/lib/Core/Scheduler/Cache.js +17 -0
- package/lib/Core/Scheduler/CancelledCommandException.js +15 -0
- package/lib/Core/Scheduler/Scheduler.js +294 -0
- package/lib/Core/Style.js +660 -0
- package/lib/Core/StyleOptions.js +486 -0
- package/lib/Core/System/Capabilities.js +63 -0
- package/lib/Core/Tile/Tile.js +205 -0
- package/lib/Core/Tile/TileGrid.js +49 -0
- package/lib/Core/TileGeometry.js +124 -0
- package/lib/Core/TileMesh.js +108 -0
- package/lib/Core/View.js +1115 -0
- package/lib/Layer/C3DTilesLayer.js +459 -0
- package/lib/Layer/ColorLayer.js +154 -0
- package/lib/Layer/CopcLayer.js +63 -0
- package/lib/Layer/ElevationLayer.js +139 -0
- package/lib/Layer/EntwinePointTileLayer.js +71 -0
- package/lib/Layer/FeatureGeometryLayer.js +77 -0
- package/lib/Layer/GeoidLayer.js +80 -0
- package/lib/Layer/GeometryLayer.js +233 -0
- package/lib/Layer/InfoLayer.js +64 -0
- package/lib/Layer/LabelLayer.js +469 -0
- package/lib/Layer/Layer.js +335 -0
- package/lib/Layer/LayerUpdateState.js +89 -0
- package/lib/Layer/LayerUpdateStrategy.js +80 -0
- package/lib/Layer/OGC3DTilesLayer.js +543 -0
- package/lib/Layer/OrientedImageLayer.js +227 -0
- package/lib/Layer/PointCloudLayer.js +405 -0
- package/lib/Layer/Potree2Layer.js +171 -0
- package/lib/Layer/PotreeLayer.js +72 -0
- package/lib/Layer/RasterLayer.js +37 -0
- package/lib/Layer/ReferencingLayerProperties.js +62 -0
- package/lib/Layer/TiledGeometryLayer.js +459 -0
- package/lib/Loader/LASLoader.js +193 -0
- package/lib/Loader/Potree2BrotliLoader.js +261 -0
- package/lib/Loader/Potree2Loader.js +207 -0
- package/lib/Main.js +113 -0
- package/lib/MainBundle.js +4 -0
- package/lib/Parser/B3dmParser.js +174 -0
- package/lib/Parser/CameraCalibrationParser.js +94 -0
- package/lib/Parser/GDFParser.js +72 -0
- package/lib/Parser/GTXParser.js +75 -0
- package/lib/Parser/GeoJsonParser.js +212 -0
- package/lib/Parser/GpxParser.js +25 -0
- package/lib/Parser/ISGParser.js +71 -0
- package/lib/Parser/KMLParser.js +25 -0
- package/lib/Parser/LASParser.js +137 -0
- package/lib/Parser/MapBoxUrlParser.js +83 -0
- package/lib/Parser/PntsParser.js +131 -0
- package/lib/Parser/Potree2BinParser.js +92 -0
- package/lib/Parser/PotreeBinParser.js +106 -0
- package/lib/Parser/PotreeCinParser.js +29 -0
- package/lib/Parser/ShapefileParser.js +78 -0
- package/lib/Parser/VectorTileParser.js +215 -0
- package/lib/Parser/XbilParser.js +120 -0
- package/lib/Parser/deprecated/LegacyGLTFLoader.js +1386 -0
- package/lib/Parser/iGLTFLoader.js +168 -0
- package/lib/Process/3dTilesProcessing.js +304 -0
- package/lib/Process/FeatureProcessing.js +76 -0
- package/lib/Process/LayeredMaterialNodeProcessing.js +229 -0
- package/lib/Process/ObjectRemovalHelper.js +97 -0
- package/lib/Process/handlerNodeError.js +23 -0
- package/lib/Provider/3dTilesProvider.js +149 -0
- package/lib/Provider/DataSourceProvider.js +24 -0
- package/lib/Provider/Fetcher.js +233 -0
- package/lib/Provider/PointCloudProvider.js +45 -0
- package/lib/Provider/TileProvider.js +16 -0
- package/lib/Provider/URLBuilder.js +116 -0
- package/lib/Renderer/Camera.js +281 -0
- package/lib/Renderer/Color.js +56 -0
- package/lib/Renderer/ColorLayersOrdering.js +115 -0
- package/lib/Renderer/CommonMaterial.js +31 -0
- package/lib/Renderer/Label2DRenderer.js +192 -0
- package/lib/Renderer/LayeredMaterial.js +243 -0
- package/lib/Renderer/OBB.js +150 -0
- package/lib/Renderer/OrientedImageCamera.js +118 -0
- package/lib/Renderer/OrientedImageMaterial.js +167 -0
- package/lib/Renderer/PointsMaterial.js +485 -0
- package/lib/Renderer/RasterTile.js +243 -0
- package/lib/Renderer/RenderMode.js +31 -0
- package/lib/Renderer/Shader/ShaderChunk.js +160 -0
- package/lib/Renderer/Shader/ShaderUtils.js +47 -0
- package/lib/Renderer/SphereHelper.js +17 -0
- package/lib/Renderer/WebXR.js +51 -0
- package/lib/Renderer/c3DEngine.js +214 -0
- package/lib/Source/C3DTilesGoogleSource.js +74 -0
- package/lib/Source/C3DTilesIonSource.js +54 -0
- package/lib/Source/C3DTilesSource.js +30 -0
- package/lib/Source/CopcSource.js +126 -0
- package/lib/Source/EntwinePointTileSource.js +72 -0
- package/lib/Source/FileSource.js +188 -0
- package/lib/Source/OGC3DTilesGoogleSource.js +29 -0
- package/lib/Source/OGC3DTilesIonSource.js +34 -0
- package/lib/Source/OGC3DTilesSource.js +21 -0
- package/lib/Source/OrientedImageSource.js +59 -0
- package/lib/Source/Potree2Source.js +167 -0
- package/lib/Source/PotreeSource.js +82 -0
- package/lib/Source/Source.js +202 -0
- package/lib/Source/TMSSource.js +144 -0
- package/lib/Source/VectorTilesSource.js +182 -0
- package/lib/Source/WFSSource.js +170 -0
- package/lib/Source/WMSSource.js +167 -0
- package/lib/Source/WMTSSource.js +92 -0
- package/lib/ThreeExtended/capabilities/WebGL.js +69 -0
- package/lib/ThreeExtended/libs/ktx-parse.module.js +506 -0
- package/lib/ThreeExtended/libs/zstddec.module.js +29 -0
- package/lib/ThreeExtended/loaders/DDSLoader.js +200 -0
- package/lib/ThreeExtended/loaders/DRACOLoader.js +400 -0
- package/lib/ThreeExtended/loaders/GLTFLoader.js +2879 -0
- package/lib/ThreeExtended/loaders/KTX2Loader.js +709 -0
- package/lib/ThreeExtended/math/ColorSpaces.js +59 -0
- package/lib/ThreeExtended/utils/BufferGeometryUtils.js +846 -0
- package/lib/ThreeExtended/utils/WorkerPool.js +70 -0
- package/lib/Utils/CameraUtils.js +554 -0
- package/lib/Utils/DEMUtils.js +350 -0
- package/lib/Utils/FeaturesUtils.js +156 -0
- package/lib/Utils/Gradients.js +16 -0
- package/lib/Utils/ThreeUtils.js +115 -0
- package/lib/Utils/gui/C3DTilesStyle.js +218 -0
- package/lib/Utils/gui/Main.js +7 -0
- package/lib/Utils/gui/Minimap.js +152 -0
- package/lib/Utils/gui/Navigation.js +245 -0
- package/lib/Utils/gui/Scale.js +104 -0
- package/lib/Utils/gui/Searchbar.js +234 -0
- package/lib/Utils/gui/Widget.js +80 -0
- package/lib/Utils/placeObjectOnGround.js +136 -0
- package/lib/Worker/LASLoaderWorker.js +19 -0
- package/lib/Worker/Potree2Worker.js +21 -0
- package/package.json +2 -2
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { chooseNextLevelToFetch } from "../Layer/LayerUpdateStrategy.js";
|
|
2
|
+
import LayerUpdateState from "../Layer/LayerUpdateState.js";
|
|
3
|
+
import handlingError from "./handlerNodeError.js";
|
|
4
|
+
function materialCommandQueuePriorityFunction(material) {
|
|
5
|
+
// We know that 'node' is visible because commands can only be
|
|
6
|
+
// issued for visible nodes.
|
|
7
|
+
// TODO: need priorization of displayed nodes
|
|
8
|
+
// Then prefer displayed node over non-displayed one
|
|
9
|
+
return material.visible ? 100 : 10;
|
|
10
|
+
}
|
|
11
|
+
function refinementCommandCancellationFn(cmd) {
|
|
12
|
+
if (!cmd.requester.parent || !cmd.requester.material) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
// Cancel the command if the tile already has a better texture.
|
|
16
|
+
// This is only needed for elevation layers, because we may have several
|
|
17
|
+
// concurrent layers but we can only use one texture.
|
|
18
|
+
if (cmd.layer.isElevationLayer && cmd.requester.material.getElevationLayer() && cmd.targetLevel <= cmd.requester.material.getElevationLayer().level) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Cancel the command if the layer was removed between command scheduling and command execution
|
|
23
|
+
if (!cmd.requester.layerUpdateState[cmd.layer.id] || !cmd.layer.source._featuresCaches[cmd.layer.crs]) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
return !cmd.requester.material.visible;
|
|
27
|
+
}
|
|
28
|
+
function buildCommand(view, layer, extentsSource, extentsDestination, requester) {
|
|
29
|
+
return {
|
|
30
|
+
view,
|
|
31
|
+
layer,
|
|
32
|
+
extentsSource,
|
|
33
|
+
extentsDestination,
|
|
34
|
+
requester,
|
|
35
|
+
priority: materialCommandQueuePriorityFunction(requester.material),
|
|
36
|
+
earlyDropFunction: refinementCommandCancellationFn,
|
|
37
|
+
partialLoading: true
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function computePitchs(textures, extentsDestination) {
|
|
41
|
+
return extentsDestination.map((ext, i) => ext.offsetToParent(textures[i].extent));
|
|
42
|
+
}
|
|
43
|
+
export function updateLayeredMaterialNodeImagery(context, layer, node, parent) {
|
|
44
|
+
const material = node.material;
|
|
45
|
+
if (!parent || !material) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const extentsDestination = node.getExtentsByProjection(layer.crs);
|
|
49
|
+
const zoom = extentsDestination[0].zoom;
|
|
50
|
+
if (zoom > layer.zoom.max || zoom < layer.zoom.min) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
let nodeLayer = material.getLayer(layer.id);
|
|
54
|
+
|
|
55
|
+
// Initialisation
|
|
56
|
+
if (node.layerUpdateState[layer.id] === undefined) {
|
|
57
|
+
node.layerUpdateState[layer.id] = new LayerUpdateState();
|
|
58
|
+
if (!layer.source.extentInsideLimit(node.extent, zoom)) {
|
|
59
|
+
// we also need to check that tile's parent doesn't have a texture for this layer,
|
|
60
|
+
// because even if this tile is outside of the layer, it could inherit it's
|
|
61
|
+
// parent texture
|
|
62
|
+
if (!(!layer.noTextureParentOutsideLimit && parent.material && parent.material.getLayer && parent.material.getLayer(layer.id))) {
|
|
63
|
+
node.layerUpdateState[layer.id].noMoreUpdatePossible();
|
|
64
|
+
return;
|
|
65
|
+
} // ok, we're going to inherit our parent's texture
|
|
66
|
+
}
|
|
67
|
+
if (!nodeLayer) {
|
|
68
|
+
// Create new raster node
|
|
69
|
+
nodeLayer = layer.setupRasterNode(node);
|
|
70
|
+
|
|
71
|
+
// Init the node by parent
|
|
72
|
+
const parentLayer = parent.material?.getLayer(layer.id);
|
|
73
|
+
nodeLayer.initFromParent(parentLayer, extentsDestination);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Proposed new process, two separate processes:
|
|
77
|
+
// * FIRST PASS: initNodeXXXFromParent and get out of the function
|
|
78
|
+
// * SECOND PASS: Fetch best texture
|
|
79
|
+
|
|
80
|
+
// The two-step allows you to filter out unnecessary requests
|
|
81
|
+
// Indeed in the second pass, their state (not visible or not displayed) can block them to fetch
|
|
82
|
+
if (nodeLayer.level >= layer.source.zoom.min) {
|
|
83
|
+
context.view.notifyChange(node, false);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Node is hidden, no need to update it
|
|
89
|
+
if (!material.visible) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// An update is pending / or impossible -> abort
|
|
94
|
+
if (!layer.visible || !node.layerUpdateState[layer.id].canTryUpdate()) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (nodeLayer.level >= extentsDestination[0].zoom) {
|
|
98
|
+
// default decision method
|
|
99
|
+
node.layerUpdateState[layer.id].noMoreUpdatePossible();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// is fetching data from this layer disabled?
|
|
104
|
+
if (layer.frozen) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const failureParams = node.layerUpdateState[layer.id].failureParams;
|
|
108
|
+
const destinationLevel = extentsDestination[0].zoom || node.level;
|
|
109
|
+
const targetLevel = chooseNextLevelToFetch(layer.updateStrategy.type, node, destinationLevel, nodeLayer.level, layer, failureParams);
|
|
110
|
+
if (!layer.source.isVectorSource && targetLevel <= nodeLayer.level || targetLevel > destinationLevel) {
|
|
111
|
+
if (failureParams.lowestLevelError != Infinity) {
|
|
112
|
+
// this is the highest level found in case of error.
|
|
113
|
+
node.layerUpdateState[layer.id].noMoreUpdatePossible();
|
|
114
|
+
}
|
|
115
|
+
return;
|
|
116
|
+
} else if (!layer.source.extentInsideLimit(node.extent, targetLevel)) {
|
|
117
|
+
node.layerUpdateState[layer.id].noData({
|
|
118
|
+
targetLevel
|
|
119
|
+
});
|
|
120
|
+
context.view.notifyChange(node, false);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const extentsSource = extentsDestination.map(e => e.tiledExtentParent(targetLevel));
|
|
124
|
+
node.layerUpdateState[layer.id].newTry();
|
|
125
|
+
const command = buildCommand(context.view, layer, extentsSource, extentsDestination, node);
|
|
126
|
+
return context.scheduler.execute(command).then(results => {
|
|
127
|
+
// Does nothing if the layer has been removed while command was being or waiting to be executed
|
|
128
|
+
if (!node.layerUpdateState[layer.id]) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const textures = results.map((texture, index) => texture != null ? texture : {
|
|
132
|
+
isTexture: false,
|
|
133
|
+
extent: extentsDestination[index]
|
|
134
|
+
});
|
|
135
|
+
// TODO: Handle error : result is undefined in provider. throw error
|
|
136
|
+
const pitchs = computePitchs(textures, extentsDestination);
|
|
137
|
+
nodeLayer.setTextures(textures, pitchs);
|
|
138
|
+
node.layerUpdateState[layer.id].success();
|
|
139
|
+
}, err => handlingError(err, node, layer, targetLevel, context.view));
|
|
140
|
+
}
|
|
141
|
+
export function updateLayeredMaterialNodeElevation(context, layer, node, parent) {
|
|
142
|
+
const material = node.material;
|
|
143
|
+
if (!parent || !material) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// TODO: we need either
|
|
148
|
+
// - compound or exclusive layers
|
|
149
|
+
// - support for multiple elevation layers
|
|
150
|
+
|
|
151
|
+
// Elevation is currently handled differently from color layers.
|
|
152
|
+
// This is caused by a LayeredMaterial limitation: only 1 elevation texture
|
|
153
|
+
// can be used (where a tile can have N textures x M layers)
|
|
154
|
+
const extentsDestination = node.getExtentsByProjection(layer.crs);
|
|
155
|
+
const zoom = extentsDestination[0].zoom;
|
|
156
|
+
if (zoom > layer.zoom.max || zoom < layer.zoom.min) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
// Init elevation layer, and inherit from parent if possible
|
|
160
|
+
let nodeLayer = material.getElevationLayer();
|
|
161
|
+
if (!nodeLayer) {
|
|
162
|
+
nodeLayer = layer.setupRasterNode(node);
|
|
163
|
+
}
|
|
164
|
+
if (node.layerUpdateState[layer.id] === undefined) {
|
|
165
|
+
node.layerUpdateState[layer.id] = new LayerUpdateState();
|
|
166
|
+
const parentLayer = parent.material?.getLayer(layer.id);
|
|
167
|
+
nodeLayer.initFromParent(parentLayer, extentsDestination);
|
|
168
|
+
if (nodeLayer.level >= layer.source.zoom.min) {
|
|
169
|
+
context.view.notifyChange(node, false);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Possible conditions to *not* update the elevation texture
|
|
175
|
+
if (layer.frozen || !material.visible || !node.layerUpdateState[layer.id].canTryUpdate()) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const failureParams = node.layerUpdateState[layer.id].failureParams;
|
|
179
|
+
const targetLevel = chooseNextLevelToFetch(layer.updateStrategy.type, node, extentsDestination[0].zoom, nodeLayer.level, layer, failureParams);
|
|
180
|
+
if (targetLevel <= nodeLayer.level || targetLevel > extentsDestination[0].zoom) {
|
|
181
|
+
node.layerUpdateState[layer.id].noMoreUpdatePossible();
|
|
182
|
+
return;
|
|
183
|
+
} else if (!layer.source.extentInsideLimit(node.extent, targetLevel)) {
|
|
184
|
+
node.layerUpdateState[layer.id].noData({
|
|
185
|
+
targetLevel
|
|
186
|
+
});
|
|
187
|
+
context.view.notifyChange(node, false);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const extentsSource = extentsDestination.map(e => e.tiledExtentParent(targetLevel));
|
|
191
|
+
node.layerUpdateState[layer.id].newTry();
|
|
192
|
+
const command = buildCommand(context.view, layer, extentsSource, extentsDestination, node);
|
|
193
|
+
return context.scheduler.execute(command).then(results => {
|
|
194
|
+
// Does nothing if the layer has been removed while command was being or waiting to be executed
|
|
195
|
+
if (!node.layerUpdateState[layer.id]) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Do not apply the new texture if its level is < than the current
|
|
200
|
+
// one. This is only needed for elevation layers, because we may
|
|
201
|
+
// have several concurrent layers but we can only use one texture.
|
|
202
|
+
if (targetLevel <= nodeLayer.level) {
|
|
203
|
+
node.layerUpdateState[layer.id].noMoreUpdatePossible();
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const pitchs = computePitchs(results, extentsDestination);
|
|
207
|
+
nodeLayer.setTextures(results, pitchs);
|
|
208
|
+
node.layerUpdateState[layer.id].success();
|
|
209
|
+
}, err => handlingError(err, node, layer, targetLevel, context.view));
|
|
210
|
+
}
|
|
211
|
+
export function removeLayeredMaterialNodeLayer(layerId) {
|
|
212
|
+
/**
|
|
213
|
+
* @param {TileMesh} node - The node to udpate.
|
|
214
|
+
*/
|
|
215
|
+
return function (node) {
|
|
216
|
+
if (node.material?.removeLayer) {
|
|
217
|
+
if (node.material.elevationLayerIds.indexOf(layerId) > -1) {
|
|
218
|
+
node.setBBoxZ({
|
|
219
|
+
min: 0,
|
|
220
|
+
max: 0
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
node.material.removeLayer(layerId);
|
|
224
|
+
}
|
|
225
|
+
if (node.layerUpdateState && node.layerUpdateState[layerId]) {
|
|
226
|
+
delete node.layerUpdateState[layerId];
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
function disposeSingleMaterialAndTextures(material) {
|
|
2
|
+
material.dispose();
|
|
3
|
+
// dispose textures
|
|
4
|
+
for (const key of Object.keys(material)) {
|
|
5
|
+
const val = material[key];
|
|
6
|
+
if (val && val.isTexture) {
|
|
7
|
+
val.dispose();
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export default {
|
|
12
|
+
/**
|
|
13
|
+
* Cleanup obj to release three.js allocated resources
|
|
14
|
+
* @param {Object3D} obj object to release
|
|
15
|
+
*/
|
|
16
|
+
cleanup(obj) {
|
|
17
|
+
obj.layer = null;
|
|
18
|
+
|
|
19
|
+
// THREE.Scene dispose function displays a deprecation message
|
|
20
|
+
if (!obj.isScene && typeof obj.dispose === 'function') {
|
|
21
|
+
obj.dispose();
|
|
22
|
+
} else {
|
|
23
|
+
if (obj.geometry) {
|
|
24
|
+
obj.geometry.dispose();
|
|
25
|
+
// the Object Removal Helper causes inconsistencies
|
|
26
|
+
// when it assigns null to a geometry present in the Cache.
|
|
27
|
+
// Actually, the cache can provide a mesh whose geometry is null.
|
|
28
|
+
// see https://github.com/iTowns/itowns/issues/869
|
|
29
|
+
// obj.geometry = null;
|
|
30
|
+
}
|
|
31
|
+
if (obj.material) {
|
|
32
|
+
if (Array.isArray(obj.material)) {
|
|
33
|
+
for (const material of obj.material) {
|
|
34
|
+
disposeSingleMaterialAndTextures(material);
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
disposeSingleMaterialAndTextures(obj.material);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
obj.dispatchEvent({
|
|
41
|
+
type: 'dispose'
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
/**
|
|
46
|
+
* Remove obj's children belonging to a layer.
|
|
47
|
+
* Neither obj nor its children will be disposed!
|
|
48
|
+
* @param {Layer} layer The layer that objects must belong to. Other object are ignored
|
|
49
|
+
* @param {Object3D} obj The Object3D we want to clean
|
|
50
|
+
* @return {Array} an array of removed Object3D from obj (not including the recursive removals)
|
|
51
|
+
*/
|
|
52
|
+
removeChildren(layer, obj) {
|
|
53
|
+
const toRemove = obj.children.filter(c => (c.layer && c.layer.id) === layer.id);
|
|
54
|
+
obj.remove(...toRemove);
|
|
55
|
+
return toRemove;
|
|
56
|
+
},
|
|
57
|
+
/**
|
|
58
|
+
* Remove an obj and all its children belonging to a layer and only cleanup the obj (and not its children).
|
|
59
|
+
* obj will be disposed but its children **won't**!
|
|
60
|
+
* @param {Layer} layer The layer that objects must belong to. Other object are ignored
|
|
61
|
+
* @param {Object3D} obj The Object3D we want to clean
|
|
62
|
+
* @return {Array} an array of removed Object3D from obj (not including the recursive removals)
|
|
63
|
+
*/
|
|
64
|
+
removeChildrenAndCleanup(layer, obj) {
|
|
65
|
+
const toRemove = obj.children.filter(c => (c.layer && c.layer.id) === layer.id);
|
|
66
|
+
obj.remove(...toRemove);
|
|
67
|
+
if (obj.layer === layer) {
|
|
68
|
+
this.cleanup(obj);
|
|
69
|
+
}
|
|
70
|
+
return toRemove;
|
|
71
|
+
},
|
|
72
|
+
/**
|
|
73
|
+
* Recursively remove an obj and all its children belonging to a layer.
|
|
74
|
+
* All removed obj will have their geometry/material disposed.
|
|
75
|
+
* @param {Layer} layer The layer that objects must belong to. Other object are ignored
|
|
76
|
+
* @param {Object3D} obj The Object3D we want to clean
|
|
77
|
+
* @return {Array} an array of removed Object3D from obj (not including the recursive removals)
|
|
78
|
+
*/
|
|
79
|
+
removeChildrenAndCleanupRecursively(layer, obj) {
|
|
80
|
+
// Objects are filtered by id because the obj hierarchy may also contain labels that have been added as childs
|
|
81
|
+
// of the objects which have their own removal logic
|
|
82
|
+
let toRemove = obj.children.filter(c => c.layer && c.layer.id === layer.id);
|
|
83
|
+
const linked = obj.link && obj.link[layer.id];
|
|
84
|
+
if (linked?.children.length) {
|
|
85
|
+
toRemove = toRemove.concat(linked.children);
|
|
86
|
+
delete obj.link[layer.id];
|
|
87
|
+
}
|
|
88
|
+
for (const c of toRemove) {
|
|
89
|
+
this.removeChildrenAndCleanupRecursively(layer, c);
|
|
90
|
+
}
|
|
91
|
+
obj.remove(...toRemove);
|
|
92
|
+
if (obj.layer && obj.layer.id === layer.id) {
|
|
93
|
+
this.cleanup(obj);
|
|
94
|
+
}
|
|
95
|
+
return toRemove;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// max retry loading before changing the status to definitiveError
|
|
2
|
+
const MAX_RETRY = 4;
|
|
3
|
+
export default function handlingError(err, node, layer, targetLevel, view) {
|
|
4
|
+
// Cancel error handling if the layer was removed between command scheduling and its execution
|
|
5
|
+
if (!node.layerUpdateState[layer.id]) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
if (err.isCancelledCommandException) {
|
|
9
|
+
node.layerUpdateState[layer.id].success();
|
|
10
|
+
} else if (err instanceof SyntaxError) {
|
|
11
|
+
node.layerUpdateState[layer.id].failure(0, true);
|
|
12
|
+
} else {
|
|
13
|
+
const definitiveError = node.layerUpdateState[layer.id].errorCount > MAX_RETRY;
|
|
14
|
+
node.layerUpdateState[layer.id].failure(Date.now(), definitiveError, {
|
|
15
|
+
targetLevel
|
|
16
|
+
});
|
|
17
|
+
if (!definitiveError) {
|
|
18
|
+
window.setTimeout(() => {
|
|
19
|
+
view.notifyChange(node, false);
|
|
20
|
+
}, node.layerUpdateState[layer.id].secondsUntilNextTry() * 1000);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import B3dmParser from "../Parser/B3dmParser.js";
|
|
3
|
+
import PntsParser from "../Parser/PntsParser.js";
|
|
4
|
+
import Fetcher from "./Fetcher.js";
|
|
5
|
+
import ReferLayerProperties from "../Layer/ReferencingLayerProperties.js";
|
|
6
|
+
import PointsMaterial from "../Renderer/PointsMaterial.js";
|
|
7
|
+
// A bit weird but temporary until we remove this deprecated provider. Mainly to benefit from the enableDracoLoader and enableKtx2Loader
|
|
8
|
+
// methods.
|
|
9
|
+
import { itownsGLTFLoader } from "../Layer/OGC3DTilesLayer.js";
|
|
10
|
+
const utf8Decoder = new TextDecoder();
|
|
11
|
+
function b3dmToMesh(data, layer, url) {
|
|
12
|
+
const urlBase = THREE.LoaderUtils.extractUrlBase(url);
|
|
13
|
+
const options = {
|
|
14
|
+
gltfUpAxis: layer.tileset.asset.gltfUpAxis,
|
|
15
|
+
urlBase,
|
|
16
|
+
overrideMaterials: layer.overrideMaterials,
|
|
17
|
+
doNotPatchMaterial: layer.doNotPatchMaterial,
|
|
18
|
+
registeredExtensions: layer.registeredExtensions,
|
|
19
|
+
layer
|
|
20
|
+
};
|
|
21
|
+
return B3dmParser.parse(data, options).then(result => {
|
|
22
|
+
const batchTable = result.batchTable;
|
|
23
|
+
// object3d is actually a THREE.Scene
|
|
24
|
+
const object3d = result.gltf.scene;
|
|
25
|
+
return {
|
|
26
|
+
batchTable,
|
|
27
|
+
object3d
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function gltfToMesh(data, layer, url) {
|
|
32
|
+
const urlBase = THREE.LoaderUtils.extractUrlBase(url);
|
|
33
|
+
return itownsGLTFLoader.parseAsync(data, urlBase).then(result => ({
|
|
34
|
+
object3d: result.scene
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
function pntsParse(data, layer) {
|
|
38
|
+
return PntsParser.parse(data, layer.registeredExtensions).then(result => {
|
|
39
|
+
const material = layer.material ? layer.material.clone() : new PointsMaterial({
|
|
40
|
+
size: 1,
|
|
41
|
+
mode: layer.pntsMode,
|
|
42
|
+
shape: layer.pntsShape,
|
|
43
|
+
classificationScheme: layer.classification,
|
|
44
|
+
sizeMode: layer.pntsSizeMode,
|
|
45
|
+
minAttenuatedSize: layer.pntsMinAttenuatedSize,
|
|
46
|
+
maxAttenuatedSize: layer.pntsMaxAttenuatedSize
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// refer material properties in the layer so when layers opacity and visibility is updated, the material is
|
|
50
|
+
// automatically updated
|
|
51
|
+
ReferLayerProperties(material, layer);
|
|
52
|
+
|
|
53
|
+
// creation points with geometry and material
|
|
54
|
+
const points = new THREE.Points(result.point.geometry, material);
|
|
55
|
+
if (result.point.offset) {
|
|
56
|
+
points.position.copy(result.point.offset);
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
object3d: points,
|
|
60
|
+
batchTable: result.batchTable
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
export function configureTile(tile, layer, metadata, parent) {
|
|
65
|
+
tile.frustumCulled = false;
|
|
66
|
+
tile.layer = layer;
|
|
67
|
+
|
|
68
|
+
// parse metadata
|
|
69
|
+
if (metadata.transform) {
|
|
70
|
+
tile.applyMatrix4(metadata.transform);
|
|
71
|
+
}
|
|
72
|
+
tile.geometricError = metadata.geometricError;
|
|
73
|
+
tile.tileId = metadata.tileId;
|
|
74
|
+
if (metadata.refine) {
|
|
75
|
+
tile.additiveRefinement = metadata.refine.toUpperCase() === 'ADD';
|
|
76
|
+
} else {
|
|
77
|
+
tile.additiveRefinement = parent ? parent.additiveRefinement : false;
|
|
78
|
+
}
|
|
79
|
+
tile.viewerRequestVolume = metadata.viewerRequestVolume;
|
|
80
|
+
tile.boundingVolume = metadata.boundingVolume;
|
|
81
|
+
tile.updateMatrixWorld();
|
|
82
|
+
}
|
|
83
|
+
function executeCommand(command) {
|
|
84
|
+
const layer = command.layer;
|
|
85
|
+
const metadata = command.metadata;
|
|
86
|
+
const tile = new THREE.Object3D();
|
|
87
|
+
configureTile(tile, layer, metadata, command.requester);
|
|
88
|
+
// Patch for supporting 3D Tiles pre 1.0 (metadata.content.url) and 1.0
|
|
89
|
+
// (metadata.content.uri)
|
|
90
|
+
const path = metadata.content && (metadata.content.url || metadata.content.uri);
|
|
91
|
+
const setLayer = obj => {
|
|
92
|
+
obj.userData.metadata = metadata;
|
|
93
|
+
obj.layer = layer;
|
|
94
|
+
};
|
|
95
|
+
if (path) {
|
|
96
|
+
// Check if we have relative or absolute url (with tileset's lopocs for example)
|
|
97
|
+
let url = path.startsWith('http') ? path : metadata.baseURL + path;
|
|
98
|
+
if (layer.source.isC3DTilesGoogleSource) {
|
|
99
|
+
url = layer.source.getTileUrl(url);
|
|
100
|
+
}
|
|
101
|
+
const supportedFormats = {
|
|
102
|
+
b3dm: b3dmToMesh,
|
|
103
|
+
pnts: pntsParse,
|
|
104
|
+
gltf: gltfToMesh
|
|
105
|
+
};
|
|
106
|
+
return Fetcher.arrayBuffer(url, layer.source.networkOptions).then(result => {
|
|
107
|
+
if (result !== undefined) {
|
|
108
|
+
let func;
|
|
109
|
+
const magic = utf8Decoder.decode(new Uint8Array(result, 0, 4));
|
|
110
|
+
if (magic[0] === '{') {
|
|
111
|
+
result = JSON.parse(utf8Decoder.decode(new Uint8Array(result)));
|
|
112
|
+
// Another specifics of 3D tiles from Google: tilesets in tilesets are required from the root base
|
|
113
|
+
// url and not from their parent base url
|
|
114
|
+
const newPrefix = layer.source.isC3DTilesGoogleSource ? layer.source.baseUrl : url.slice(0, url.lastIndexOf('/') + 1);
|
|
115
|
+
layer.tileset.extendTileset(result, metadata.tileId, newPrefix, layer.registeredExtensions);
|
|
116
|
+
} else if (magic == 'b3dm') {
|
|
117
|
+
func = supportedFormats.b3dm;
|
|
118
|
+
} else if (magic == 'pnts') {
|
|
119
|
+
layer.hasPnts = true;
|
|
120
|
+
func = supportedFormats.pnts;
|
|
121
|
+
} else if (magic == 'glTF') {
|
|
122
|
+
func = supportedFormats.gltf;
|
|
123
|
+
} else {
|
|
124
|
+
return Promise.reject(`Unsupported magic code ${magic}`);
|
|
125
|
+
}
|
|
126
|
+
if (func) {
|
|
127
|
+
// TODO: request should be delayed if there is a viewerRequestVolume
|
|
128
|
+
return func(result, layer, url).then(content => {
|
|
129
|
+
tile.content = content.object3d;
|
|
130
|
+
if (content.batchTable) {
|
|
131
|
+
tile.batchTable = content.batchTable;
|
|
132
|
+
}
|
|
133
|
+
tile.add(content.object3d);
|
|
134
|
+
tile.traverse(setLayer);
|
|
135
|
+
return tile;
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
tile.traverse(setLayer);
|
|
140
|
+
return tile;
|
|
141
|
+
});
|
|
142
|
+
} else {
|
|
143
|
+
tile.traverse(setLayer);
|
|
144
|
+
return Promise.resolve(tile);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
export default {
|
|
148
|
+
executeCommand
|
|
149
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
executeCommand(command) {
|
|
3
|
+
const layer = command.layer;
|
|
4
|
+
const src = command.extentsSource;
|
|
5
|
+
const dst = command.extentsDestination || src;
|
|
6
|
+
const promises = src.map((from, i) => layer.getData(from, dst[i]));
|
|
7
|
+
|
|
8
|
+
// partialLoading sets the return promise as fulfilled if at least one sub-promise is fulfilled
|
|
9
|
+
// It waits until all promises are resolved
|
|
10
|
+
if (command.partialLoading) {
|
|
11
|
+
return Promise.allSettled(promises).then(results => {
|
|
12
|
+
const anyFulfilledPromise = results.find(promise => promise.status === 'fulfilled');
|
|
13
|
+
if (!anyFulfilledPromise) {
|
|
14
|
+
// All promises failed -> reject
|
|
15
|
+
return Promise.reject(new Error('Failed to load any data'));
|
|
16
|
+
}
|
|
17
|
+
return results.map(prom => prom.value ? prom.value : null);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Without partialLoading, the return promise is rejected as soon as any sub-promise is rejected
|
|
22
|
+
return Promise.all(promises);
|
|
23
|
+
}
|
|
24
|
+
};
|