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,543 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
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';
|
|
6
|
+
import GeometryLayer from "./GeometryLayer.js";
|
|
7
|
+
import iGLTFLoader from "../Parser/iGLTFLoader.js";
|
|
8
|
+
import { DRACOLoader } from "../ThreeExtended/loaders/DRACOLoader.js";
|
|
9
|
+
import { KTX2Loader } from "../ThreeExtended/loaders/KTX2Loader.js";
|
|
10
|
+
import ReferLayerProperties from "./ReferencingLayerProperties.js";
|
|
11
|
+
import PointsMaterial, { PNTS_MODE, PNTS_SHAPE, PNTS_SIZE_MODE, ClassificationScheme } from "../Renderer/PointsMaterial.js";
|
|
12
|
+
import { VIEW_EVENTS } from "../Core/View.js";
|
|
13
|
+
const _raycaster = new THREE.Raycaster();
|
|
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
|
+
|
|
20
|
+
// Internal instance of GLTFLoader, passed to 3d-tiles-renderer-js to support GLTF 1.0 and 2.0
|
|
21
|
+
// Temporary exported to be used in deprecated B3dmParser
|
|
22
|
+
export const itownsGLTFLoader = new iGLTFLoader();
|
|
23
|
+
itownsGLTFLoader.register(() => new GLTFMeshFeaturesExtension());
|
|
24
|
+
itownsGLTFLoader.register(() => new GLTFStructuralMetadataExtension());
|
|
25
|
+
itownsGLTFLoader.register(() => new GLTFCesiumRTCExtension());
|
|
26
|
+
export const OGC3DTILES_LAYER_EVENTS = {
|
|
27
|
+
/**
|
|
28
|
+
* Fired when a new root or child tile set is loaded
|
|
29
|
+
* @event OGC3DTilesLayer#load-tile-set
|
|
30
|
+
* @type {Object}
|
|
31
|
+
* @property {Object} tileset - the tileset json parsed in an Object
|
|
32
|
+
* @property {String} url - tileset url
|
|
33
|
+
*/
|
|
34
|
+
LOAD_TILE_SET: 'load-tile-set',
|
|
35
|
+
/**
|
|
36
|
+
* Fired when a tile model is loaded
|
|
37
|
+
* @event OGC3DTilesLayer#load-model
|
|
38
|
+
* @type {Object}
|
|
39
|
+
* @property {THREE.Group} scene - the model (tile content) parsed in a THREE.GROUP
|
|
40
|
+
* @property {Object} tile - the tile metadata from the tileset
|
|
41
|
+
*/
|
|
42
|
+
LOAD_MODEL: 'load-model',
|
|
43
|
+
/**
|
|
44
|
+
* Fired when a tile model is disposed
|
|
45
|
+
* @event OGC3DTilesLayer#dispose-model
|
|
46
|
+
* @type {Object}
|
|
47
|
+
* @property {THREE.Group} scene - the model (tile content) that is disposed
|
|
48
|
+
* @property {Object} tile - the tile metadata from the tileset
|
|
49
|
+
*/
|
|
50
|
+
DISPOSE_MODEL: 'dispose-model',
|
|
51
|
+
/**
|
|
52
|
+
* Fired when a tiles visibility changes
|
|
53
|
+
* @event OGC3DTilesLayer#tile-visibility-change
|
|
54
|
+
* @type {Object}
|
|
55
|
+
* @property {THREE.Group} scene - the model (tile content) parsed in a THREE.GROUP
|
|
56
|
+
* @property {Object} tile - the tile metadata from the tileset
|
|
57
|
+
* @property {boolean} visible - the tile visible state
|
|
58
|
+
*/
|
|
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'
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Enable loading 3D Tiles with [Draco](https://google.github.io/draco/) geometry extension.
|
|
76
|
+
*
|
|
77
|
+
* @param {String} path path to draco library folder containing the JS and WASM decoder libraries. They can be found in
|
|
78
|
+
* [itowns examples](https://github.com/iTowns/itowns/tree/master/examples/libs/draco).
|
|
79
|
+
* @param {Object} [config] optional configuration for Draco decoder (see threejs'
|
|
80
|
+
* [setDecoderConfig](https://threejs.org/docs/index.html?q=draco#examples/en/loaders/DRACOLoader.setDecoderConfig) that
|
|
81
|
+
* is called under the hood with this configuration for details.
|
|
82
|
+
*/
|
|
83
|
+
export function enableDracoLoader(path, config) {
|
|
84
|
+
if (!path) {
|
|
85
|
+
throw new Error('Path to draco folder is mandatory');
|
|
86
|
+
}
|
|
87
|
+
const dracoLoader = new DRACOLoader();
|
|
88
|
+
dracoLoader.setDecoderPath(path);
|
|
89
|
+
if (config) {
|
|
90
|
+
dracoLoader.setDecoderConfig(config);
|
|
91
|
+
}
|
|
92
|
+
itownsGLTFLoader.setDRACOLoader(dracoLoader);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Enable loading 3D Tiles with [KTX2](https://www.khronos.org/ktx/) texture extension.
|
|
97
|
+
*
|
|
98
|
+
* @param {String} path path to ktx2 library folder containing the JS and WASM decoder libraries. They can be found in
|
|
99
|
+
* [itowns examples](https://github.com/iTowns/itowns/tree/master/examples/libs/basis).
|
|
100
|
+
* @param {THREE.WebGLRenderer} renderer the threejs renderer
|
|
101
|
+
*/
|
|
102
|
+
export function enableKtx2Loader(path, renderer) {
|
|
103
|
+
if (!path || !renderer) {
|
|
104
|
+
throw new Error('Path to ktx2 folder and renderer are mandatory');
|
|
105
|
+
}
|
|
106
|
+
const ktx2Loader = new KTX2Loader();
|
|
107
|
+
ktx2Loader.setTranscoderPath(path);
|
|
108
|
+
ktx2Loader.detectSupport(renderer);
|
|
109
|
+
itownsGLTFLoader.setKTX2Loader(ktx2Loader);
|
|
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
|
+
}
|
|
208
|
+
class OGC3DTilesLayer extends GeometryLayer {
|
|
209
|
+
/**
|
|
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
|
+
*
|
|
218
|
+
* @extends Layer
|
|
219
|
+
*
|
|
220
|
+
* @param {String} id - unique layer id.
|
|
221
|
+
* @param {Object} config - layer specific configuration
|
|
222
|
+
* @param {OGC3DTilesSource} config.source - data source configuration
|
|
223
|
+
* @param {String} [config.pntsMode = PNTS_MODE.COLOR] Point cloud coloring mode (passed to {@link PointsMaterial}).
|
|
224
|
+
* Only 'COLOR' or 'CLASSIFICATION' are possible. COLOR uses RGB colors of the points,
|
|
225
|
+
* CLASSIFICATION uses a classification property of the batch table to color points.
|
|
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.
|
|
228
|
+
* (passed to {@link PointsMaterial}).
|
|
229
|
+
* @param {String} [config.pntsSizeMode = PNTS_SIZE_MODE.VALUE] {@link PointsMaterial} Point cloud size mode (passed to {@link PointsMaterial}).
|
|
230
|
+
* Only 'VALUE' or 'ATTENUATED' are possible. VALUE use constant size, ATTENUATED compute size depending on distance
|
|
231
|
+
* from point to camera.
|
|
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.
|
|
234
|
+
*/
|
|
235
|
+
constructor(id, config) {
|
|
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);
|
|
246
|
+
this.isOGC3DTilesLayer = true;
|
|
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;
|
|
256
|
+
this.tilesRenderer = new TilesRenderer(this.source.url);
|
|
257
|
+
if (config.source.isOGC3DTilesIonSource) {
|
|
258
|
+
this.tilesRenderer.registerPlugin(new CesiumIonAuthPlugin({
|
|
259
|
+
apiToken: config.source.accessToken,
|
|
260
|
+
assetId: config.source.assetId,
|
|
261
|
+
autoRefreshToken: true
|
|
262
|
+
}));
|
|
263
|
+
} else if (config.source.isOGC3DTilesGoogleSource) {
|
|
264
|
+
this.tilesRenderer.registerPlugin(new GoogleCloudAuthPlugin({
|
|
265
|
+
apiToken: config.source.key,
|
|
266
|
+
autoRefreshToken: true
|
|
267
|
+
}));
|
|
268
|
+
}
|
|
269
|
+
this.tilesRenderer.registerPlugin(new ImplicitTilingPlugin());
|
|
270
|
+
this.tilesRenderer.manager.addHandler(/\.gltf$/, itownsGLTFLoader);
|
|
271
|
+
this.object3d.add(this.tilesRenderer.group);
|
|
272
|
+
|
|
273
|
+
// Add an initialization step that is resolved when the root tileset is loaded (see this._setup below), meaning
|
|
274
|
+
// that the layer will be marked ready when the tileset has been loaded.
|
|
275
|
+
this._res = this.addInitializationStep();
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* @type {number}
|
|
279
|
+
*/
|
|
280
|
+
this.sseThreshold = this.tilesRenderer.errorTarget;
|
|
281
|
+
Object.defineProperty(this, 'sseThreshold', {
|
|
282
|
+
get() {
|
|
283
|
+
return this.tilesRenderer.errorTarget;
|
|
284
|
+
},
|
|
285
|
+
set(value) {
|
|
286
|
+
this.tilesRenderer.errorTarget = value;
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
if (config.sseThreshold) {
|
|
290
|
+
this.sseThreshold = config.sseThreshold;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
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.
|
|
298
|
+
* @private
|
|
299
|
+
*/
|
|
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;
|
|
306
|
+
} else {
|
|
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
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Binds 3d-tiles-renderer events to this layer.
|
|
320
|
+
* @private
|
|
321
|
+
*/
|
|
322
|
+
_setupEvents() {
|
|
323
|
+
for (const ev of Object.values(OGC3DTILES_LAYER_EVENTS)) {
|
|
324
|
+
this.tilesRenderer.addEventListener(ev, e => {
|
|
325
|
+
this.dispatchEvent(e);
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Setup 3D tiles renderer js TilesRenderer with the camera, binds events and start updating. Executed when the
|
|
332
|
+
* layer has been added to the view.
|
|
333
|
+
* @param {View} view - the view the layer has been added to.
|
|
334
|
+
* @private
|
|
335
|
+
*/
|
|
336
|
+
_setup(view) {
|
|
337
|
+
this.tilesRenderer.setCamera(view.camera3D);
|
|
338
|
+
this.tilesRenderer.setResolutionFromRenderer(view.camera3D, view.renderer);
|
|
339
|
+
// Setup whenReady to be fullfiled when the root tileset has been loaded
|
|
340
|
+
let rootTilesetLoaded = false;
|
|
341
|
+
this.tilesRenderer.addEventListener('load-tile-set', () => {
|
|
342
|
+
view.notifyChange(this);
|
|
343
|
+
if (!rootTilesetLoaded) {
|
|
344
|
+
rootTilesetLoaded = true;
|
|
345
|
+
this._res();
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
this.tilesRenderer.addEventListener('load-model', e => {
|
|
349
|
+
const {
|
|
350
|
+
scene
|
|
351
|
+
} = e;
|
|
352
|
+
scene.traverse(obj => {
|
|
353
|
+
this._assignFinalMaterial(obj);
|
|
354
|
+
this._assignFinalAttributes(obj);
|
|
355
|
+
});
|
|
356
|
+
view.notifyChange(this);
|
|
357
|
+
});
|
|
358
|
+
this._setupCacheAndQueues(view);
|
|
359
|
+
this._setupEvents();
|
|
360
|
+
|
|
361
|
+
// Start loading tileset and tiles
|
|
362
|
+
this.tilesRenderer.update();
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Replace materials from GLTFLoader by our own custom materials. Note that
|
|
367
|
+
* the replaced materials are not compiled yet and will be disposed by the
|
|
368
|
+
* GC.
|
|
369
|
+
* @param {Object3D} model
|
|
370
|
+
* @private
|
|
371
|
+
*/
|
|
372
|
+
_assignFinalMaterial(model) {
|
|
373
|
+
let material = model.material;
|
|
374
|
+
if (model.isPoints) {
|
|
375
|
+
const pointsMaterial = new PointsMaterial({
|
|
376
|
+
mode: this.pntsMode,
|
|
377
|
+
shape: this.pntsShape,
|
|
378
|
+
classificationScheme: this.classification,
|
|
379
|
+
sizeMode: this.pntsSizeMode,
|
|
380
|
+
minAttenuatedSize: this.pntsMinAttenuatedSize,
|
|
381
|
+
maxAttenuatedSize: this.pntsMaxAttenuatedSize
|
|
382
|
+
});
|
|
383
|
+
pointsMaterial.copy(material);
|
|
384
|
+
material = pointsMaterial;
|
|
385
|
+
}
|
|
386
|
+
if (material) {
|
|
387
|
+
ReferLayerProperties(material, this);
|
|
388
|
+
}
|
|
389
|
+
model.material = material;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* @param {Object3D} model
|
|
394
|
+
* @private
|
|
395
|
+
*/
|
|
396
|
+
_assignFinalAttributes(model) {
|
|
397
|
+
const geometry = model.geometry;
|
|
398
|
+
const batchTable = model.batchTable;
|
|
399
|
+
|
|
400
|
+
// Setup classification bufferAttribute
|
|
401
|
+
if (model.isPoints) {
|
|
402
|
+
const classificationData = batchTable?.getPropertyArray('Classification');
|
|
403
|
+
if (classificationData) {
|
|
404
|
+
geometry.setAttribute('classification', new THREE.BufferAttribute(classificationData, 1));
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
preUpdate(context) {
|
|
409
|
+
this.scale = context.camera._preSSE;
|
|
410
|
+
this.tilesRenderer.update();
|
|
411
|
+
return null; // don't return any element because 3d-tiles-renderer already updates them
|
|
412
|
+
}
|
|
413
|
+
update() {
|
|
414
|
+
// empty, elements are updated by 3d-tiles-renderer
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Deletes the layer and frees associated memory
|
|
419
|
+
*/
|
|
420
|
+
delete() {
|
|
421
|
+
this.tilesRenderer.dispose();
|
|
422
|
+
}
|
|
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
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Get the attributes for the closest intersection from a list of
|
|
452
|
+
* intersects.
|
|
453
|
+
* @param {Array<THREE.Intersection>} intersects - An array containing all
|
|
454
|
+
* objects picked under mouse coordinates computed with view.pickObjectsAt(..).
|
|
455
|
+
* @returns {Object | null} - An object containing
|
|
456
|
+
*/
|
|
457
|
+
getC3DTileFeatureFromIntersectsArray(intersects) {
|
|
458
|
+
if (!intersects.length) {
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
461
|
+
const {
|
|
462
|
+
face,
|
|
463
|
+
index,
|
|
464
|
+
object,
|
|
465
|
+
instanceId
|
|
466
|
+
} = intersects[0];
|
|
467
|
+
|
|
468
|
+
/** @type{number|null} */
|
|
469
|
+
let batchId;
|
|
470
|
+
if (object.isPoints && index) {
|
|
471
|
+
batchId = object.geometry.getAttribute('_BATCHID')?.getX(index) ?? index;
|
|
472
|
+
} else if (object.isMesh && face) {
|
|
473
|
+
batchId = object.geometry.getAttribute('_BATCHID')?.getX(face.a) ?? instanceId;
|
|
474
|
+
}
|
|
475
|
+
if (batchId === undefined) {
|
|
476
|
+
return null;
|
|
477
|
+
}
|
|
478
|
+
let tileObject = object;
|
|
479
|
+
while (!tileObject.batchTable) {
|
|
480
|
+
tileObject = tileObject.parent;
|
|
481
|
+
}
|
|
482
|
+
return tileObject.batchTable.getDataFromId(batchId);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Get all 3D objects (mesh and points primitives) as intersects at the
|
|
487
|
+
* given non-normalized screen coordinates.
|
|
488
|
+
* @param {View} view - The view instance.
|
|
489
|
+
* @param {THREE.Vector2} coords - The coordinates to pick in the view. It
|
|
490
|
+
* should have at least `x` and `y` properties.
|
|
491
|
+
* @param {number} radius - Radius of the picking circle.
|
|
492
|
+
* @param {Array} [target=[]] - Target array to push results too
|
|
493
|
+
* @returns {Array} Array containing all target objects picked under the
|
|
494
|
+
* specified coordinates.
|
|
495
|
+
*/
|
|
496
|
+
pickObjectsAt(view, coords) {
|
|
497
|
+
let target = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
|
|
498
|
+
const camera = view.camera.camera3D;
|
|
499
|
+
_raycaster.setFromCamera(view.viewToNormalizedCoords(coords), camera);
|
|
500
|
+
_raycaster.near = camera.near;
|
|
501
|
+
_raycaster.far = camera.far;
|
|
502
|
+
_raycaster.firstHitOnly = 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);
|
|
510
|
+
return target;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// eslint-disable-next-line no-unused-vars
|
|
514
|
+
attach() {
|
|
515
|
+
console.warn('[OGC3DTilesLayer]: Attaching / detaching layers is not yet implemented for OGC3DTilesLayer.');
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// eslint-disable-next-line no-unused-vars
|
|
519
|
+
detach() {
|
|
520
|
+
console.warn('[OGC3DTilesLayer]: Attaching / detaching layers is not yet implemented for OGC3DTilesLayer.');
|
|
521
|
+
return true;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// eslint-disable-next-line no-unused-vars
|
|
525
|
+
getObjectToUpdateForAttachedLayers() {
|
|
526
|
+
return null;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Executes a callback for each tile of this layer tileset.
|
|
531
|
+
*
|
|
532
|
+
* @param {Function} callback The callback to execute for each tile. Has the following two parameters:
|
|
533
|
+
* 1. tile (Object) - the JSON tile
|
|
534
|
+
* 2. scene (THREE.Object3D | null) - The tile content. Contains a `batchTable` property. Can be null if the tile
|
|
535
|
+
* has not yet been loaded.
|
|
536
|
+
*/
|
|
537
|
+
forEachTile(callback) {
|
|
538
|
+
this.tilesRenderer.traverse(tile => {
|
|
539
|
+
callback(tile, tile.cached.scene);
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
export default OGC3DTilesLayer;
|