itowns 2.44.3-next.4 → 2.44.3-next.40
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/CODING.md +1 -1
- package/CONTRIBUTORS.md +1 -0
- package/dist/debug.js +1 -1
- package/dist/debug.js.map +1 -1
- package/dist/itowns.js +1 -1
- package/dist/itowns.js.LICENSE.txt +0 -2
- package/dist/itowns.js.map +1 -1
- package/dist/itowns_widgets.js +1 -1
- package/dist/itowns_widgets.js.map +1 -1
- package/examples/3dtiles_loader.html +123 -48
- package/examples/config.json +3 -10
- package/examples/copc_simple_loader.html +15 -5
- package/examples/effects_stereo.html +2 -2
- package/examples/entwine_3d_loader.html +3 -1
- package/examples/entwine_simple_loader.html +1 -1
- package/examples/images/itowns_logo.svg +123 -0
- package/examples/js/plugins/COGParser.js +1 -1
- package/examples/jsm/OGC3DTilesHelper.js +6 -1
- package/examples/layers/JSONLayers/GeoidMNT.json +3 -1
- package/examples/misc_collada.html +2 -2
- package/examples/source_file_geojson_3d.html +0 -1
- package/examples/source_file_kml_raster_usgs.html +0 -1
- package/examples/source_stream_wfs_raster.html +0 -7
- package/examples/vector_tile_mapbox_raster.html +91 -0
- package/examples/view_3d_map_webxr.html +3 -1
- package/examples/view_multi_25d.html +2 -2
- package/lib/Controls/GlobeControls.js +45 -28
- package/lib/Controls/StateControl.js +5 -2
- package/lib/Converter/Feature2Mesh.js +10 -4
- package/lib/Converter/Feature2Texture.js +6 -1
- package/lib/Converter/convertToTile.js +3 -8
- package/lib/Converter/textureConverter.js +4 -5
- package/lib/Core/Deprecated/Undeprecator.js +0 -1
- package/lib/Core/Feature.js +3 -4
- package/lib/Core/Geographic/Coordinates.js +143 -132
- package/lib/Core/Geographic/Crs.js +140 -145
- package/lib/Core/Geographic/Extent.js +221 -397
- package/lib/Core/Geographic/GeoidGrid.js +1 -1
- package/lib/Core/MainLoop.js +1 -3
- package/lib/Core/Math/Ellipsoid.js +62 -21
- package/lib/Core/Prefab/Globe/Atmosphere.js +4 -8
- package/lib/Core/Prefab/Globe/GlobeLayer.js +22 -15
- package/lib/Core/Prefab/Globe/GlobeTileBuilder.js +111 -0
- package/lib/Core/Prefab/GlobeView.js +2 -7
- package/lib/Core/Prefab/Planar/PlanarLayer.js +17 -11
- package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +43 -43
- package/lib/Core/Prefab/TileBuilder.js +42 -40
- package/lib/Core/Prefab/computeBufferTileGeometry.js +195 -130
- package/lib/Core/Scheduler/Cache.js +1 -240
- package/lib/Core/Style.js +34 -495
- package/lib/Core/StyleOptions.js +486 -0
- package/lib/Core/Tile/Tile.js +207 -0
- package/lib/Core/Tile/TileGrid.js +49 -0
- package/lib/Core/TileGeometry.js +112 -28
- package/lib/Core/TileMesh.js +3 -3
- package/lib/Core/View.js +15 -8
- package/lib/Layer/C3DTilesLayer.js +20 -16
- package/lib/Layer/ColorLayer.js +35 -9
- package/lib/Layer/CopcLayer.js +7 -2
- package/lib/Layer/ElevationLayer.js +39 -7
- package/lib/Layer/EntwinePointTileLayer.js +14 -7
- package/lib/Layer/FeatureGeometryLayer.js +20 -6
- package/lib/Layer/GeometryLayer.js +42 -11
- package/lib/Layer/LabelLayer.js +45 -27
- package/lib/Layer/Layer.js +92 -61
- package/lib/Layer/OGC3DTilesLayer.js +212 -56
- package/lib/Layer/OrientedImageLayer.js +11 -5
- package/lib/Layer/PointCloudLayer.js +76 -30
- package/lib/Layer/Potree2Layer.js +9 -2
- package/lib/Layer/PotreeLayer.js +10 -3
- package/lib/Layer/RasterLayer.js +12 -2
- package/lib/Layer/TiledGeometryLayer.js +69 -13
- package/lib/Main.js +2 -2
- package/lib/Parser/GeoJsonParser.js +1 -1
- package/lib/Parser/VectorTileParser.js +42 -29
- package/lib/Parser/XbilParser.js +14 -2
- package/lib/Provider/Fetcher.js +5 -1
- package/lib/Provider/URLBuilder.js +22 -11
- package/lib/Renderer/Camera.js +1 -1
- package/lib/Renderer/Label2DRenderer.js +9 -7
- package/lib/Renderer/OBB.js +11 -13
- package/lib/Renderer/PointsMaterial.js +5 -5
- package/lib/Renderer/RasterTile.js +1 -2
- package/lib/Renderer/SphereHelper.js +0 -6
- package/lib/Source/CopcSource.js +13 -2
- package/lib/Source/EntwinePointTileSource.js +14 -4
- package/lib/Source/FileSource.js +9 -10
- package/lib/Source/OrientedImageSource.js +2 -2
- package/lib/Source/Source.js +26 -46
- package/lib/Source/TMSSource.js +10 -9
- package/lib/Source/VectorTilesSource.js +38 -34
- package/lib/Source/WFSSource.js +18 -13
- package/lib/Source/WMSSource.js +56 -18
- package/lib/Source/WMTSSource.js +13 -7
- package/lib/ThreeExtended/libs/ktx-parse.module.js +310 -274
- package/lib/ThreeExtended/loaders/DRACOLoader.js +3 -2
- package/lib/ThreeExtended/loaders/GLTFLoader.js +6 -3
- package/lib/ThreeExtended/loaders/KTX2Loader.js +144 -60
- package/lib/ThreeExtended/math/ColorSpaces.js +59 -0
- package/lib/Utils/CameraUtils.js +1 -1
- package/lib/Utils/gui/C3DTilesStyle.js +2 -3
- package/lib/Utils/placeObjectOnGround.js +0 -1
- package/package.json +10 -8
- package/examples/3dtiles_25d.html +0 -120
- package/examples/3dtiles_basic.html +0 -94
- package/examples/3dtiles_batch_table.html +0 -86
- package/examples/3dtiles_ion.html +0 -126
- package/examples/3dtiles_pointcloud.html +0 -95
- package/lib/Core/Prefab/Globe/BuilderEllipsoidTile.js +0 -110
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
|
-
import { TilesRenderer
|
|
2
|
+
import { TilesRenderer } from '3d-tiles-renderer';
|
|
3
|
+
import { GLTFStructuralMetadataExtension, GLTFMeshFeaturesExtension, GLTFCesiumRTCExtension, CesiumIonAuthPlugin, GoogleCloudAuthPlugin, ImplicitTilingPlugin
|
|
4
|
+
// eslint-disable-next-line import/no-unresolved
|
|
5
|
+
} from '3d-tiles-renderer/plugins';
|
|
3
6
|
import GeometryLayer from "./GeometryLayer.js";
|
|
4
7
|
import iGLTFLoader from "../Parser/iGLTFLoader.js";
|
|
5
8
|
import { DRACOLoader } from "../ThreeExtended/loaders/DRACOLoader.js";
|
|
6
9
|
import { KTX2Loader } from "../ThreeExtended/loaders/KTX2Loader.js";
|
|
7
10
|
import ReferLayerProperties from "./ReferencingLayerProperties.js";
|
|
8
11
|
import PointsMaterial, { PNTS_MODE, PNTS_SHAPE, PNTS_SIZE_MODE, ClassificationScheme } from "../Renderer/PointsMaterial.js";
|
|
12
|
+
import { VIEW_EVENTS } from "../Core/View.js";
|
|
9
13
|
const _raycaster = new THREE.Raycaster();
|
|
10
14
|
|
|
15
|
+
// Stores lruCache, downloadQueue and parseQueue for each id of view {@link View}
|
|
16
|
+
// every time a tileset has been added
|
|
17
|
+
// https://github.com/iTowns/itowns/issues/2426
|
|
18
|
+
const viewers = {};
|
|
19
|
+
|
|
11
20
|
// Internal instance of GLTFLoader, passed to 3d-tiles-renderer-js to support GLTF 1.0 and 2.0
|
|
12
21
|
// Temporary exported to be used in deprecated B3dmParser
|
|
13
22
|
export const itownsGLTFLoader = new iGLTFLoader();
|
|
14
23
|
itownsGLTFLoader.register(() => new GLTFMeshFeaturesExtension());
|
|
15
24
|
itownsGLTFLoader.register(() => new GLTFStructuralMetadataExtension());
|
|
16
25
|
itownsGLTFLoader.register(() => new GLTFCesiumRTCExtension());
|
|
17
|
-
|
|
18
|
-
// Instantiated by the first tileset. Used to share cache and download and parse queues between tilesets
|
|
19
|
-
let lruCache = null;
|
|
20
|
-
let downloadQueue = null;
|
|
21
|
-
let parseQueue = null;
|
|
22
26
|
export const OGC3DTILES_LAYER_EVENTS = {
|
|
23
27
|
/**
|
|
24
28
|
* Fired when a new root or child tile set is loaded
|
|
@@ -52,7 +56,19 @@ export const OGC3DTILES_LAYER_EVENTS = {
|
|
|
52
56
|
* @property {Object} tile - the tile metadata from the tileset
|
|
53
57
|
* @property {boolean} visible - the tile visible state
|
|
54
58
|
*/
|
|
55
|
-
TILE_VISIBILITY_CHANGE: 'tile-visibility-change'
|
|
59
|
+
TILE_VISIBILITY_CHANGE: 'tile-visibility-change',
|
|
60
|
+
/**
|
|
61
|
+
* Fired when a new batch of tiles start loading (can be fired multiple times, e.g. when the camera moves and new tiles
|
|
62
|
+
* start loading)
|
|
63
|
+
* @event OGC3DTilesLayer#tiles-load-start
|
|
64
|
+
*/
|
|
65
|
+
TILES_LOAD_START: 'tiles-load-start',
|
|
66
|
+
/**
|
|
67
|
+
* Fired when all visible tiles are loaded (can be fired multiple times, e.g. when the camera moves and new tiles
|
|
68
|
+
* are loaded)
|
|
69
|
+
* @event OGC3DTilesLayer#tiles-load-end
|
|
70
|
+
*/
|
|
71
|
+
TILES_LOAD_END: 'tiles-load-end'
|
|
56
72
|
};
|
|
57
73
|
|
|
58
74
|
/**
|
|
@@ -92,32 +108,151 @@ export function enableKtx2Loader(path, renderer) {
|
|
|
92
108
|
ktx2Loader.detectSupport(renderer);
|
|
93
109
|
itownsGLTFLoader.setKTX2Loader(ktx2Loader);
|
|
94
110
|
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Enable loading 3D Tiles and GLTF with
|
|
114
|
+
* [meshopt](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_meshopt_compression/README.md) compression extension.
|
|
115
|
+
*
|
|
116
|
+
* @param {MeshOptDecoder.constructor} MeshOptDecoder - The Meshopt decoder
|
|
117
|
+
* module.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* import * as itowns from 'itowns';
|
|
121
|
+
* import { MeshoptDecoder } from 'three/addons/libs/meshopt_decoder.module.js';
|
|
122
|
+
*
|
|
123
|
+
* // Enable support of EXT_meshopt_compression
|
|
124
|
+
* itowns.enableMeshoptDecoder(MeshoptDecoder);
|
|
125
|
+
*/
|
|
126
|
+
export function enableMeshoptDecoder(MeshOptDecoder) {
|
|
127
|
+
if (!MeshOptDecoder) {
|
|
128
|
+
throw new Error('MeshOptDecoder module is mandatory');
|
|
129
|
+
}
|
|
130
|
+
itownsGLTFLoader.setMeshoptDecoder(MeshOptDecoder);
|
|
131
|
+
}
|
|
132
|
+
async function getMeshFeatures(meshFeatures, options) {
|
|
133
|
+
const {
|
|
134
|
+
faceIndex,
|
|
135
|
+
barycoord
|
|
136
|
+
} = options;
|
|
137
|
+
const features = await meshFeatures.getFeaturesAsync(faceIndex, barycoord);
|
|
138
|
+
return {
|
|
139
|
+
features,
|
|
140
|
+
featureIds: meshFeatures.getFeatureInfo()
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function getStructuralMetadata(structuralMetadata, options) {
|
|
144
|
+
const {
|
|
145
|
+
index,
|
|
146
|
+
faceIndex,
|
|
147
|
+
barycoord,
|
|
148
|
+
tableIndices,
|
|
149
|
+
features
|
|
150
|
+
} = options;
|
|
151
|
+
const tableData = [];
|
|
152
|
+
if (tableIndices !== undefined && features !== undefined) {
|
|
153
|
+
structuralMetadata.getPropertyTableData(tableIndices, features, tableData);
|
|
154
|
+
}
|
|
155
|
+
const attributeData = [];
|
|
156
|
+
if (index !== undefined) {
|
|
157
|
+
structuralMetadata.getPropertyAttributeData(index, attributeData);
|
|
158
|
+
}
|
|
159
|
+
const textureData = [];
|
|
160
|
+
if (faceIndex !== undefined) {
|
|
161
|
+
structuralMetadata.getPropertyTextureData(faceIndex, barycoord, textureData);
|
|
162
|
+
}
|
|
163
|
+
const metadata = [...tableData, ...textureData, ...attributeData];
|
|
164
|
+
return metadata;
|
|
165
|
+
}
|
|
166
|
+
async function getMetadataFromIntersection(intersection) {
|
|
167
|
+
const {
|
|
168
|
+
point,
|
|
169
|
+
object,
|
|
170
|
+
face,
|
|
171
|
+
faceIndex
|
|
172
|
+
} = intersection;
|
|
173
|
+
const {
|
|
174
|
+
meshFeatures,
|
|
175
|
+
structuralMetadata
|
|
176
|
+
} = object.userData;
|
|
177
|
+
const barycoord = new THREE.Vector3();
|
|
178
|
+
if (face) {
|
|
179
|
+
const position = object.geometry.getAttribute('position');
|
|
180
|
+
const triangle = new THREE.Triangle().setFromAttributeAndIndices(position, face.a, face.b, face.c);
|
|
181
|
+
triangle.a.applyMatrix4(object.matrixWorld);
|
|
182
|
+
triangle.b.applyMatrix4(object.matrixWorld);
|
|
183
|
+
triangle.c.applyMatrix4(object.matrixWorld);
|
|
184
|
+
triangle.getBarycoord(point, barycoord);
|
|
185
|
+
} else {
|
|
186
|
+
barycoord.set(0, 0, 0);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// EXT_mesh_features
|
|
190
|
+
const {
|
|
191
|
+
features,
|
|
192
|
+
featureIds
|
|
193
|
+
} = meshFeatures ? await getMeshFeatures(meshFeatures, {
|
|
194
|
+
faceIndex,
|
|
195
|
+
barycoord
|
|
196
|
+
}) : {};
|
|
197
|
+
const tableIndices = featureIds?.map(p => p.propertyTable);
|
|
198
|
+
|
|
199
|
+
// EXT_structural_metadata
|
|
200
|
+
const metadata = structuralMetadata ? getStructuralMetadata(structuralMetadata, {
|
|
201
|
+
...intersection,
|
|
202
|
+
barycoord,
|
|
203
|
+
tableIndices,
|
|
204
|
+
features
|
|
205
|
+
}) : [];
|
|
206
|
+
return metadata;
|
|
207
|
+
}
|
|
95
208
|
class OGC3DTilesLayer extends GeometryLayer {
|
|
96
209
|
/**
|
|
97
210
|
* Layer for [3D Tiles](https://www.ogc.org/standard/3dtiles/) datasets.
|
|
211
|
+
*
|
|
212
|
+
* Advanced configuration note: 3D Tiles rendering is delegated to 3DTilesRendererJS that exposes several
|
|
213
|
+
* configuration options accessible through the tilesRenderer property of this class. see the
|
|
214
|
+
* [3DTilesRendererJS doc](https://github.com/NASA-AMMOS/3DTilesRendererJS/blob/master/README.md). Also note that
|
|
215
|
+
* the cache is shared amongst 3D tiles layers and can be configured through tilesRenderer.lruCache (see the
|
|
216
|
+
* [following documentation](https://github.com/NASA-AMMOS/3DTilesRendererJS/blob/master/README.md#lrucache-1).
|
|
217
|
+
*
|
|
98
218
|
* @extends Layer
|
|
99
219
|
*
|
|
100
220
|
* @param {String} id - unique layer id.
|
|
101
221
|
* @param {Object} config - layer specific configuration
|
|
102
222
|
* @param {OGC3DTilesSource} config.source - data source configuration
|
|
103
|
-
* @param {String} [config.pntsMode= PNTS_MODE.COLOR] Point cloud coloring mode (passed to {@link PointsMaterial}).
|
|
223
|
+
* @param {String} [config.pntsMode = PNTS_MODE.COLOR] Point cloud coloring mode (passed to {@link PointsMaterial}).
|
|
104
224
|
* Only 'COLOR' or 'CLASSIFICATION' are possible. COLOR uses RGB colors of the points,
|
|
105
225
|
* CLASSIFICATION uses a classification property of the batch table to color points.
|
|
106
|
-
* @param {ClassificationScheme} [config.classificationScheme] {@link PointsMaterial} classification scheme
|
|
107
|
-
* @param {String} [config.pntsShape= PNTS_SHAPE.CIRCLE] Point cloud point shape. Only 'CIRCLE' or 'SQUARE' are possible.
|
|
226
|
+
* @param {ClassificationScheme} [config.classificationScheme = ClassificationScheme.DEFAULT] {@link PointsMaterial} classification scheme
|
|
227
|
+
* @param {String} [config.pntsShape = PNTS_SHAPE.CIRCLE] Point cloud point shape. Only 'CIRCLE' or 'SQUARE' are possible.
|
|
108
228
|
* (passed to {@link PointsMaterial}).
|
|
109
|
-
* @param {String} [config.pntsSizeMode= PNTS_SIZE_MODE.VALUE] {@link PointsMaterial} Point cloud size mode (passed to {@link PointsMaterial}).
|
|
229
|
+
* @param {String} [config.pntsSizeMode = PNTS_SIZE_MODE.VALUE] {@link PointsMaterial} Point cloud size mode (passed to {@link PointsMaterial}).
|
|
110
230
|
* Only 'VALUE' or 'ATTENUATED' are possible. VALUE use constant size, ATTENUATED compute size depending on distance
|
|
111
231
|
* from point to camera.
|
|
112
|
-
* @param {Number} [config.pntsMinAttenuatedSize=
|
|
113
|
-
* @param {Number} [config.pntsMaxAttenuatedSize=
|
|
232
|
+
* @param {Number} [config.pntsMinAttenuatedSize = 3] Minimum scale used by 'ATTENUATED' size mode.
|
|
233
|
+
* @param {Number} [config.pntsMaxAttenuatedSize = 10] Maximum scale used by 'ATTENUATED' size mode.
|
|
114
234
|
*/
|
|
115
235
|
constructor(id, config) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
236
|
+
const {
|
|
237
|
+
pntsMode = PNTS_MODE.COLOR,
|
|
238
|
+
pntsShape = PNTS_SHAPE.CIRCLE,
|
|
239
|
+
classification = ClassificationScheme.DEFAULT,
|
|
240
|
+
pntsSizeMode = PNTS_SIZE_MODE.VALUE,
|
|
241
|
+
pntsMinAttenuatedSize = 3,
|
|
242
|
+
pntsMaxAttenuatedSize = 10,
|
|
243
|
+
...geometryLayerConfig
|
|
244
|
+
} = config;
|
|
245
|
+
super(id, new THREE.Group(), geometryLayerConfig);
|
|
119
246
|
this.isOGC3DTilesLayer = true;
|
|
120
|
-
|
|
247
|
+
// Store points material config so they can be used later to substitute points tiles material
|
|
248
|
+
// by our own PointsMaterial. These properties should eventually be managed through the Style API
|
|
249
|
+
// (see https://github.com/iTowns/itowns/issues/2336)
|
|
250
|
+
this.pntsMode = pntsMode;
|
|
251
|
+
this.pntsShape = pntsShape;
|
|
252
|
+
this.classification = classification;
|
|
253
|
+
this.pntsSizeMode = pntsSizeMode;
|
|
254
|
+
this.pntsMinAttenuatedSize = pntsMinAttenuatedSize;
|
|
255
|
+
this.pntsMaxAttenuatedSize = pntsMaxAttenuatedSize;
|
|
121
256
|
this.tilesRenderer = new TilesRenderer(this.source.url);
|
|
122
257
|
if (config.source.isOGC3DTilesIonSource) {
|
|
123
258
|
this.tilesRenderer.registerPlugin(new CesiumIonAuthPlugin({
|
|
@@ -133,8 +268,6 @@ class OGC3DTilesLayer extends GeometryLayer {
|
|
|
133
268
|
}
|
|
134
269
|
this.tilesRenderer.registerPlugin(new ImplicitTilingPlugin());
|
|
135
270
|
this.tilesRenderer.manager.addHandler(/\.gltf$/, itownsGLTFLoader);
|
|
136
|
-
this._setupCacheAndQueues();
|
|
137
|
-
this._setupEvents();
|
|
138
271
|
this.object3d.add(this.tilesRenderer.group);
|
|
139
272
|
|
|
140
273
|
// Add an initialization step that is resolved when the root tileset is loaded (see this._setup below), meaning
|
|
@@ -159,39 +292,26 @@ class OGC3DTilesLayer extends GeometryLayer {
|
|
|
159
292
|
}
|
|
160
293
|
|
|
161
294
|
/**
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
* @param {
|
|
165
|
-
* @private
|
|
166
|
-
*/
|
|
167
|
-
_handlePointsMaterialConfig(config) {
|
|
168
|
-
this.pntsMode = config.pntsMode ?? PNTS_MODE.COLOR;
|
|
169
|
-
this.pntsShape = config.pntsShape ?? PNTS_SHAPE.CIRCLE;
|
|
170
|
-
this.classification = config.classification ?? ClassificationScheme.DEFAULT;
|
|
171
|
-
this.pntsSizeMode = config.pntsSizeMode ?? PNTS_SIZE_MODE.VALUE;
|
|
172
|
-
this.pntsMinAttenuatedSize = config.pntsMinAttenuatedSize || 1;
|
|
173
|
-
this.pntsMaxAttenuatedSize = config.pntsMaxAttenuatedSize || 7;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Sets the lruCache and download and parse queues so they are shared amongst all tilesets.
|
|
295
|
+
* Sets the lruCache and download and parse queues so they are shared amongst
|
|
296
|
+
* all tilesets from a same {@link View} view.
|
|
297
|
+
* @param {View} view - view associated to this layer.
|
|
178
298
|
* @private
|
|
179
299
|
*/
|
|
180
|
-
_setupCacheAndQueues() {
|
|
181
|
-
|
|
182
|
-
|
|
300
|
+
_setupCacheAndQueues(view) {
|
|
301
|
+
const id = view.id;
|
|
302
|
+
if (viewers[id]) {
|
|
303
|
+
this.tilesRenderer.lruCache = viewers[id].lruCache;
|
|
304
|
+
this.tilesRenderer.downloadQueue = viewers[id].downloadQueue;
|
|
305
|
+
this.tilesRenderer.parseQueue = viewers[id].parseQueue;
|
|
183
306
|
} else {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
parseQueue = this.tilesRenderer.parseQueue;
|
|
193
|
-
} else {
|
|
194
|
-
this.tilesRenderer.parseQueue = parseQueue;
|
|
307
|
+
viewers[id] = {
|
|
308
|
+
lruCache: this.tilesRenderer.lruCache,
|
|
309
|
+
downloadQueue: this.tilesRenderer.downloadQueue,
|
|
310
|
+
parseQueue: this.tilesRenderer.parseQueue
|
|
311
|
+
};
|
|
312
|
+
view.addEventListener(VIEW_EVENTS.DISPOSED, evt => {
|
|
313
|
+
delete viewers[evt.target.id];
|
|
314
|
+
});
|
|
195
315
|
}
|
|
196
316
|
}
|
|
197
317
|
|
|
@@ -225,16 +345,19 @@ class OGC3DTilesLayer extends GeometryLayer {
|
|
|
225
345
|
this._res();
|
|
226
346
|
}
|
|
227
347
|
});
|
|
228
|
-
this.tilesRenderer.addEventListener('load-model',
|
|
229
|
-
|
|
348
|
+
this.tilesRenderer.addEventListener('load-model', e => {
|
|
349
|
+
const {
|
|
230
350
|
scene
|
|
231
|
-
} =
|
|
351
|
+
} = e;
|
|
232
352
|
scene.traverse(obj => {
|
|
233
353
|
this._assignFinalMaterial(obj);
|
|
234
354
|
this._assignFinalAttributes(obj);
|
|
235
355
|
});
|
|
236
356
|
view.notifyChange(this);
|
|
237
357
|
});
|
|
358
|
+
this._setupCacheAndQueues(view);
|
|
359
|
+
this._setupEvents();
|
|
360
|
+
|
|
238
361
|
// Start loading tileset and tiles
|
|
239
362
|
this.tilesRenderer.update();
|
|
240
363
|
}
|
|
@@ -298,10 +421,36 @@ class OGC3DTilesLayer extends GeometryLayer {
|
|
|
298
421
|
this.tilesRenderer.dispose();
|
|
299
422
|
}
|
|
300
423
|
|
|
424
|
+
/**
|
|
425
|
+
* Get the [metadata](https://github.com/CesiumGS/3d-tiles/tree/main/specification/Metadata)
|
|
426
|
+
* of the closest intersected object from a list of intersections.
|
|
427
|
+
*
|
|
428
|
+
* This method retrieves structured metadata stored in GLTF 2.0 assets using
|
|
429
|
+
* the [`EXT_structural_metadata`](https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_structural_metadata)
|
|
430
|
+
* extension.
|
|
431
|
+
*
|
|
432
|
+
* Internally, it uses the closest intersected point to index metadata
|
|
433
|
+
* stored in property attributes and textures.
|
|
434
|
+
*
|
|
435
|
+
* If present in GLTF 2.0 assets, this method leverages the
|
|
436
|
+
* [`EXT_mesh_features`](`https://github.com/CesiumGS/glTF/tree/3d-tiles-next/extensions/2.0/Vendor/EXT_mesh_features)
|
|
437
|
+
* extension and the returned featured to index metadata stored in property tables.
|
|
438
|
+
*
|
|
439
|
+
* @param {Array<THREE.Intersection>} intersections
|
|
440
|
+
* @returns {Promise<Object | null>} - the intersected object's metadata
|
|
441
|
+
*/
|
|
442
|
+
async getMetadataFromIntersections(intersections) {
|
|
443
|
+
if (!intersections.length) {
|
|
444
|
+
return null;
|
|
445
|
+
}
|
|
446
|
+
const metadata = await getMetadataFromIntersection(intersections[0]);
|
|
447
|
+
return metadata;
|
|
448
|
+
}
|
|
449
|
+
|
|
301
450
|
/**
|
|
302
451
|
* Get the attributes for the closest intersection from a list of
|
|
303
452
|
* intersects.
|
|
304
|
-
* @param {Array} intersects - An array containing all
|
|
453
|
+
* @param {Array<THREE.Intersection>} intersects - An array containing all
|
|
305
454
|
* objects picked under mouse coordinates computed with view.pickObjectsAt(..).
|
|
306
455
|
* @returns {Object | null} - An object containing
|
|
307
456
|
*/
|
|
@@ -312,7 +461,8 @@ class OGC3DTilesLayer extends GeometryLayer {
|
|
|
312
461
|
const {
|
|
313
462
|
face,
|
|
314
463
|
index,
|
|
315
|
-
object
|
|
464
|
+
object,
|
|
465
|
+
instanceId
|
|
316
466
|
} = intersects[0];
|
|
317
467
|
|
|
318
468
|
/** @type{number|null} */
|
|
@@ -320,7 +470,7 @@ class OGC3DTilesLayer extends GeometryLayer {
|
|
|
320
470
|
if (object.isPoints && index) {
|
|
321
471
|
batchId = object.geometry.getAttribute('_BATCHID')?.getX(index) ?? index;
|
|
322
472
|
} else if (object.isMesh && face) {
|
|
323
|
-
batchId = object.geometry.getAttribute('_BATCHID')?.getX(face.a);
|
|
473
|
+
batchId = object.geometry.getAttribute('_BATCHID')?.getX(face.a) ?? instanceId;
|
|
324
474
|
}
|
|
325
475
|
if (batchId === undefined) {
|
|
326
476
|
return null;
|
|
@@ -350,7 +500,13 @@ class OGC3DTilesLayer extends GeometryLayer {
|
|
|
350
500
|
_raycaster.near = camera.near;
|
|
351
501
|
_raycaster.far = camera.far;
|
|
352
502
|
_raycaster.firstHitOnly = true;
|
|
353
|
-
_raycaster.intersectObject(this.tilesRenderer.group, true
|
|
503
|
+
const picked = _raycaster.intersectObject(this.tilesRenderer.group, true);
|
|
504
|
+
// Store the layer of the picked object to conform to the interface of what's returned by Picking.js (used for
|
|
505
|
+
// other GeometryLayers
|
|
506
|
+
picked.forEach(p => {
|
|
507
|
+
p.layer = this;
|
|
508
|
+
});
|
|
509
|
+
target.push(...picked);
|
|
354
510
|
return target;
|
|
355
511
|
}
|
|
356
512
|
|
|
@@ -96,14 +96,20 @@ class OrientedImageLayer extends GeometryLayer {
|
|
|
96
96
|
*/
|
|
97
97
|
constructor(id) {
|
|
98
98
|
let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
99
|
-
|
|
99
|
+
const {
|
|
100
|
+
backgroundDistance,
|
|
101
|
+
background = createBackground(backgroundDistance),
|
|
102
|
+
onPanoChanged = () => {},
|
|
103
|
+
getCamerasNameFromFeature = () => {},
|
|
104
|
+
...geometryOptions
|
|
105
|
+
} = config;
|
|
100
106
|
if (config.projection) {
|
|
101
107
|
console.warn('OrientedImageLayer projection parameter is deprecated, use crs instead.');
|
|
102
108
|
config.crs = config.crs || config.projection;
|
|
103
109
|
}
|
|
104
|
-
super(id, new THREE.Group(),
|
|
110
|
+
super(id, new THREE.Group(), geometryOptions);
|
|
105
111
|
this.isOrientedImageLayer = true;
|
|
106
|
-
this.background =
|
|
112
|
+
this.background = background;
|
|
107
113
|
if (this.background) {
|
|
108
114
|
// Add layer id to easily identify the objects later on (e.g. to delete the geometries when deleting the layer)
|
|
109
115
|
this.background.layer = this.background.layer ?? {};
|
|
@@ -115,10 +121,10 @@ class OrientedImageLayer extends GeometryLayer {
|
|
|
115
121
|
this.currentPano = undefined;
|
|
116
122
|
|
|
117
123
|
// store a callback to fire event when current panoramic change
|
|
118
|
-
this.onPanoChanged =
|
|
124
|
+
this.onPanoChanged = onPanoChanged;
|
|
119
125
|
|
|
120
126
|
// function to get cameras name from panoramic feature
|
|
121
|
-
this.getCamerasNameFromFeature =
|
|
127
|
+
this.getCamerasNameFromFeature = getCamerasNameFromFeature;
|
|
122
128
|
const resolve = this.addInitializationStep();
|
|
123
129
|
this.mergeFeatures = false;
|
|
124
130
|
this.filteringExtent = false;
|
|
@@ -113,6 +113,8 @@ function changeAngleRange(layer) {
|
|
|
113
113
|
* @property {number} [maxIntensityRange=1] - The maximal intensity of the
|
|
114
114
|
* layer. Changing this value will affect the material, if it has the
|
|
115
115
|
* corresponding uniform. The value is normalized between 0 and 1.
|
|
116
|
+
*
|
|
117
|
+
* @extends GeometryLayer
|
|
116
118
|
*/
|
|
117
119
|
class PointCloudLayer extends GeometryLayer {
|
|
118
120
|
/**
|
|
@@ -120,8 +122,6 @@ class PointCloudLayer extends GeometryLayer {
|
|
|
120
122
|
* Constructs a new instance of a Point Cloud Layer. This should not be used
|
|
121
123
|
* directly, but rather implemented using `extends`.
|
|
122
124
|
*
|
|
123
|
-
* @extends GeometryLayer
|
|
124
|
-
*
|
|
125
125
|
* @param {string} id - The id of the layer, that should be unique. It is
|
|
126
126
|
* not mandatory, but an error will be emitted if this layer is added a
|
|
127
127
|
* {@link View} that already has a layer going by that id.
|
|
@@ -130,40 +130,88 @@ class PointCloudLayer extends GeometryLayer {
|
|
|
130
130
|
* contains three elements `name, protocol, extent`, these elements will be
|
|
131
131
|
* available using `layer.name` or something else depending on the property
|
|
132
132
|
* name. See the list of properties to know which one can be specified.
|
|
133
|
+
* @param {Source} config.source - Description and options of the source See @Layer.
|
|
134
|
+
* @param {number} [options.minElevationRange] - Min value for the elevation range (default value will be taken from the source.metadata).
|
|
135
|
+
* @param {number} [options.maxElevationRange] - Max value for the elevation range (default value will be taken from the source.metadata).
|
|
133
136
|
*/
|
|
134
137
|
constructor(id) {
|
|
135
138
|
let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
136
|
-
|
|
139
|
+
const {
|
|
140
|
+
object3d = new THREE.Group(),
|
|
141
|
+
group = new THREE.Group(),
|
|
142
|
+
bboxes = new THREE.Group(),
|
|
143
|
+
octreeDepthLimit = -1,
|
|
144
|
+
pointBudget = 2000000,
|
|
145
|
+
pointSize = 2,
|
|
146
|
+
sseThreshold = 2,
|
|
147
|
+
minIntensityRange = 1,
|
|
148
|
+
maxIntensityRange = 65536,
|
|
149
|
+
minElevationRange,
|
|
150
|
+
maxElevationRange,
|
|
151
|
+
minAngleRange = -90,
|
|
152
|
+
maxAngleRange = 90,
|
|
153
|
+
material = {},
|
|
154
|
+
mode = PNTS_MODE.COLOR,
|
|
155
|
+
...geometryLayerConfig
|
|
156
|
+
} = config;
|
|
157
|
+
super(id, object3d, geometryLayerConfig);
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @type {boolean}
|
|
161
|
+
* @readonly
|
|
162
|
+
*/
|
|
137
163
|
this.isPointCloudLayer = true;
|
|
138
164
|
this.protocol = 'pointcloud';
|
|
139
|
-
this.group =
|
|
165
|
+
this.group = group;
|
|
140
166
|
this.object3d.add(this.group);
|
|
141
|
-
this.bboxes =
|
|
167
|
+
this.bboxes = bboxes || new THREE.Group();
|
|
142
168
|
this.bboxes.visible = false;
|
|
143
169
|
this.object3d.add(this.bboxes);
|
|
144
170
|
this.group.updateMatrixWorld();
|
|
145
171
|
|
|
146
172
|
// default config
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
this.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
this.
|
|
156
|
-
|
|
157
|
-
|
|
173
|
+
/**
|
|
174
|
+
* @type {number}
|
|
175
|
+
*/
|
|
176
|
+
this.octreeDepthLimit = octreeDepthLimit;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* @type {number}
|
|
180
|
+
*/
|
|
181
|
+
this.pointBudget = pointBudget;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* @type {number}
|
|
185
|
+
*/
|
|
186
|
+
this.pointSize = pointSize;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* @type {number}
|
|
190
|
+
*/
|
|
191
|
+
this.sseThreshold = sseThreshold;
|
|
192
|
+
this.defineLayerProperty('minIntensityRange', minIntensityRange, changeIntensityRange);
|
|
193
|
+
this.defineLayerProperty('maxIntensityRange', maxIntensityRange, changeIntensityRange);
|
|
194
|
+
this.defineLayerProperty('minElevationRange', minElevationRange, changeElevationRange);
|
|
195
|
+
this.defineLayerProperty('maxElevationRange', maxElevationRange, changeElevationRange);
|
|
196
|
+
this.defineLayerProperty('minAngleRange', minAngleRange, changeAngleRange);
|
|
197
|
+
this.defineLayerProperty('maxAngleRange', maxAngleRange, changeAngleRange);
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @type {THREE.Material}
|
|
201
|
+
*/
|
|
202
|
+
this.material = material;
|
|
158
203
|
if (!this.material.isMaterial) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
this.material = new PointsMaterial(config.material);
|
|
204
|
+
this.material.intensityRange = new THREE.Vector2(this.minIntensityRange, this.maxIntensityRange);
|
|
205
|
+
this.material.elevationRange = new THREE.Vector2(this.minElevationRange, this.maxElevationRange);
|
|
206
|
+
this.material.angleRange = new THREE.Vector2(this.minAngleRange, this.maxAngleRange);
|
|
207
|
+
this.material = new PointsMaterial(this.material);
|
|
164
208
|
}
|
|
165
|
-
this.
|
|
166
|
-
|
|
209
|
+
this.mode = mode || PNTS_MODE.COLOR;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* @type {PointCloudNode | undefined}
|
|
213
|
+
*/
|
|
214
|
+
this.root = undefined;
|
|
167
215
|
}
|
|
168
216
|
preUpdate(context, changeSources) {
|
|
169
217
|
// See https://cesiumjs.org/hosted-apps/massiveworlds/downloads/Ring/WorldScaleTerrainRendering.pptx
|
|
@@ -245,9 +293,6 @@ class PointCloudLayer extends GeometryLayer {
|
|
|
245
293
|
redraw: true,
|
|
246
294
|
earlyDropFunction: cmd => !cmd.requester.visible || !this.visible
|
|
247
295
|
}).then(pts => {
|
|
248
|
-
if (this.onPointsCreated) {
|
|
249
|
-
this.onPointsCreated(layer, pts);
|
|
250
|
-
}
|
|
251
296
|
elt.obj = pts;
|
|
252
297
|
// store tightbbox to avoid ping-pong (bbox = larger => visible, tight => invisible)
|
|
253
298
|
elt.tightbbox = pts.tightbbox;
|
|
@@ -256,11 +301,12 @@ class PointCloudLayer extends GeometryLayer {
|
|
|
256
301
|
// be added nor cleaned
|
|
257
302
|
this.group.add(elt.obj);
|
|
258
303
|
elt.obj.updateMatrixWorld(true);
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
elt.promise = null;
|
|
304
|
+
}).catch(err => {
|
|
305
|
+
if (!err.isCancelledCommandException) {
|
|
306
|
+
return err;
|
|
263
307
|
}
|
|
308
|
+
}).finally(() => {
|
|
309
|
+
elt.promise = null;
|
|
264
310
|
});
|
|
265
311
|
}
|
|
266
312
|
}
|
|
@@ -99,13 +99,13 @@ function parseAttributes(jsonAttributes) {
|
|
|
99
99
|
* @property {boolean} isPotreeLayer - Used to checkout whether this layer
|
|
100
100
|
* is a Potree2Layer. Default is `true`. You should not change this, as it is
|
|
101
101
|
* used internally for optimisation.
|
|
102
|
+
*
|
|
103
|
+
* @extends PointCloudLayer
|
|
102
104
|
*/
|
|
103
105
|
class Potree2Layer extends PointCloudLayer {
|
|
104
106
|
/**
|
|
105
107
|
* Constructs a new instance of Potree2 layer.
|
|
106
108
|
*
|
|
107
|
-
* @extends PointCloudLayer
|
|
108
|
-
*
|
|
109
109
|
* @example
|
|
110
110
|
* // Create a new point cloud layer
|
|
111
111
|
* const points = new Potree2Layer('points',
|
|
@@ -132,6 +132,11 @@ class Potree2Layer extends PointCloudLayer {
|
|
|
132
132
|
*/
|
|
133
133
|
constructor(id, config) {
|
|
134
134
|
super(id, config);
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @type {boolean}
|
|
138
|
+
* @readonly
|
|
139
|
+
*/
|
|
135
140
|
this.isPotreeLayer = true;
|
|
136
141
|
const resolve = this.addInitializationStep();
|
|
137
142
|
this.source.whenReady.then(metadata => {
|
|
@@ -149,6 +154,8 @@ class Potree2Layer extends PointCloudLayer {
|
|
|
149
154
|
const root = new Potree2Node(0, 0, this);
|
|
150
155
|
root.bbox = boundingBox;
|
|
151
156
|
root.boundingSphere = boundingBox.getBoundingSphere(new THREE.Sphere());
|
|
157
|
+
this.minElevationRange = this.minElevationRange ?? metadata.boundingBox.min[2];
|
|
158
|
+
this.maxElevationRange = this.maxElevationRange ?? metadata.boundingBox.max[2];
|
|
152
159
|
root.id = 'r';
|
|
153
160
|
root.depth = 0;
|
|
154
161
|
root.nodeType = 2;
|
package/lib/Layer/PotreeLayer.js
CHANGED
|
@@ -10,13 +10,13 @@ bboxMesh.geometry.boundingBox = box3;
|
|
|
10
10
|
* @property {boolean} isPotreeLayer - Used to checkout whether this layer
|
|
11
11
|
* is a PotreeLayer. Default is `true`. You should not change this, as it is
|
|
12
12
|
* used internally for optimisation.
|
|
13
|
+
*
|
|
14
|
+
* @extends PointCloudLayer
|
|
13
15
|
*/
|
|
14
16
|
class PotreeLayer extends PointCloudLayer {
|
|
15
17
|
/**
|
|
16
18
|
* Constructs a new instance of Potree layer.
|
|
17
19
|
*
|
|
18
|
-
* @extends PointCloudLayer
|
|
19
|
-
*
|
|
20
20
|
* @example
|
|
21
21
|
* // Create a new point cloud layer
|
|
22
22
|
* const points = new PotreeLayer('points',
|
|
@@ -37,12 +37,17 @@ class PotreeLayer extends PointCloudLayer {
|
|
|
37
37
|
* contains three elements `name, protocol, extent`, these elements will be
|
|
38
38
|
* available using `layer.name` or something else depending on the property
|
|
39
39
|
* name. See the list of properties to know which one can be specified.
|
|
40
|
-
* @param {string} [config.crs=ESPG:4326] - The CRS of the {@link View} this
|
|
40
|
+
* @param {string} [config.crs='ESPG:4326'] - The CRS of the {@link View} this
|
|
41
41
|
* layer will be attached to. This is used to determine the extent of this
|
|
42
42
|
* layer. Default to `EPSG:4326`.
|
|
43
43
|
*/
|
|
44
44
|
constructor(id, config) {
|
|
45
45
|
super(id, config);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @type {boolean}
|
|
49
|
+
* @readonly
|
|
50
|
+
*/
|
|
46
51
|
this.isPotreeLayer = true;
|
|
47
52
|
const resolve = this.addInitializationStep();
|
|
48
53
|
this.source.whenReady.then(cloud => {
|
|
@@ -57,6 +62,8 @@ class PotreeLayer extends PointCloudLayer {
|
|
|
57
62
|
this.root = new PotreeNode(0, 0, this);
|
|
58
63
|
this.root.bbox.min.set(cloud.boundingBox.lx, cloud.boundingBox.ly, cloud.boundingBox.lz);
|
|
59
64
|
this.root.bbox.max.set(cloud.boundingBox.ux, cloud.boundingBox.uy, cloud.boundingBox.uz);
|
|
65
|
+
this.minElevationRange = this.minElevationRange ?? cloud.boundingBox.lz;
|
|
66
|
+
this.maxElevationRange = this.maxElevationRange ?? cloud.boundingBox.uz;
|
|
60
67
|
this.extent = Extent.fromBox3(this.source.crs || 'EPSG:4326', this.root.bbox);
|
|
61
68
|
return this.root.loadOctree().then(resolve);
|
|
62
69
|
});
|
package/lib/Layer/RasterLayer.js
CHANGED
|
@@ -4,8 +4,18 @@ import textureConverter from "../Converter/textureConverter.js";
|
|
|
4
4
|
import { CACHE_POLICIES } from "../Core/Scheduler/Cache.js";
|
|
5
5
|
class RasterLayer extends Layer {
|
|
6
6
|
constructor(id, config) {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const {
|
|
8
|
+
cacheLifeTime = CACHE_POLICIES.TEXTURE,
|
|
9
|
+
minFilter,
|
|
10
|
+
magFilter,
|
|
11
|
+
...layerConfig
|
|
12
|
+
} = config;
|
|
13
|
+
super(id, {
|
|
14
|
+
...layerConfig,
|
|
15
|
+
cacheLifeTime
|
|
16
|
+
});
|
|
17
|
+
this.minFilter = minFilter;
|
|
18
|
+
this.magFilter = magFilter;
|
|
9
19
|
}
|
|
10
20
|
convert(data, extentDestination) {
|
|
11
21
|
return textureConverter.convert(data, extentDestination, this);
|