itowns 2.43.2-next.24 → 2.43.2-next.26
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/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.map +1 -1
- package/dist/itowns_widgets.js +1 -1
- package/examples/3dtiles_loader.html +150 -0
- package/examples/config.json +4 -0
- package/examples/jsm/.eslintrc.cjs +38 -0
- package/examples/jsm/OGC3DTilesHelper.js +105 -0
- package/examples/misc_instancing.html +2 -1
- package/lib/Core/View.js +3 -0
- package/lib/Layer/C3DTilesLayer.js +1 -1
- package/lib/Layer/OGC3DTilesLayer.js +386 -0
- package/lib/Main.js +6 -1
- package/lib/Parser/B3dmParser.js +11 -22
- package/lib/Parser/deprecated/LegacyGLTFLoader.js +25 -5
- package/lib/Parser/iGLTFLoader.js +169 -0
- package/lib/Provider/3dTilesProvider.js +4 -2
- package/lib/Renderer/PointsMaterial.js +7 -3
- package/lib/Source/OGC3DTilesGoogleSource.js +32 -0
- package/lib/Source/OGC3DTilesIonSource.js +37 -0
- package/lib/Source/OGC3DTilesSource.js +24 -0
- package/package.json +4 -3
- package/lib/Parser/GLTFParser.js +0 -88
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { TilesRenderer, GLTFStructuralMetadataExtension, GLTFMeshFeaturesExtension, GLTFCesiumRTCExtension, CesiumIonAuthPlugin, GoogleCloudAuthPlugin, ImplicitTilingPlugin } from '3d-tiles-renderer';
|
|
3
|
+
import GeometryLayer from "./GeometryLayer.js";
|
|
4
|
+
import iGLTFLoader from "../Parser/iGLTFLoader.js";
|
|
5
|
+
import { DRACOLoader } from "../ThreeExtended/loaders/DRACOLoader.js";
|
|
6
|
+
import { KTX2Loader } from "../ThreeExtended/loaders/KTX2Loader.js";
|
|
7
|
+
import ReferLayerProperties from "./ReferencingLayerProperties.js";
|
|
8
|
+
import PointsMaterial, { PNTS_MODE, PNTS_SHAPE, PNTS_SIZE_MODE, ClassificationScheme } from "../Renderer/PointsMaterial.js";
|
|
9
|
+
const _raycaster = new THREE.Raycaster();
|
|
10
|
+
|
|
11
|
+
// Internal instance of GLTFLoader, passed to 3d-tiles-renderer-js to support GLTF 1.0 and 2.0
|
|
12
|
+
// Temporary exported to be used in deprecated B3dmParser
|
|
13
|
+
export const itownsGLTFLoader = new iGLTFLoader();
|
|
14
|
+
itownsGLTFLoader.register(() => new GLTFMeshFeaturesExtension());
|
|
15
|
+
itownsGLTFLoader.register(() => new GLTFStructuralMetadataExtension());
|
|
16
|
+
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
|
+
export const OGC3DTILES_LAYER_EVENTS = {
|
|
23
|
+
/**
|
|
24
|
+
* Fired when a new root or child tile set is loaded
|
|
25
|
+
* @event OGC3DTilesLayer#load-tile-set
|
|
26
|
+
* @type {Object}
|
|
27
|
+
* @property {Object} tileset - the tileset json parsed in an Object
|
|
28
|
+
* @property {String} url - tileset url
|
|
29
|
+
*/
|
|
30
|
+
LOAD_TILE_SET: 'load-tile-set',
|
|
31
|
+
/**
|
|
32
|
+
* Fired when a tile model is loaded
|
|
33
|
+
* @event OGC3DTilesLayer#load-model
|
|
34
|
+
* @type {Object}
|
|
35
|
+
* @property {THREE.Group} scene - the model (tile content) parsed in a THREE.GROUP
|
|
36
|
+
* @property {Object} tile - the tile metadata from the tileset
|
|
37
|
+
*/
|
|
38
|
+
LOAD_MODEL: 'load-model',
|
|
39
|
+
/**
|
|
40
|
+
* Fired when a tile model is disposed
|
|
41
|
+
* @event OGC3DTilesLayer#dispose-model
|
|
42
|
+
* @type {Object}
|
|
43
|
+
* @property {THREE.Group} scene - the model (tile content) that is disposed
|
|
44
|
+
* @property {Object} tile - the tile metadata from the tileset
|
|
45
|
+
*/
|
|
46
|
+
DISPOSE_MODEL: 'dispose-model',
|
|
47
|
+
/**
|
|
48
|
+
* Fired when a tiles visibility changes
|
|
49
|
+
* @event OGC3DTilesLayer#tile-visibility-change
|
|
50
|
+
* @type {Object}
|
|
51
|
+
* @property {THREE.Group} scene - the model (tile content) parsed in a THREE.GROUP
|
|
52
|
+
* @property {Object} tile - the tile metadata from the tileset
|
|
53
|
+
* @property {boolean} visible - the tile visible state
|
|
54
|
+
*/
|
|
55
|
+
TILE_VISIBILITY_CHANGE: 'tile-visibility-change'
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Enable loading 3D Tiles with [Draco](https://google.github.io/draco/) geometry extension.
|
|
60
|
+
*
|
|
61
|
+
* @param {String} path path to draco library folder containing the JS and WASM decoder libraries. They can be found in
|
|
62
|
+
* [itowns examples](https://github.com/iTowns/itowns/tree/master/examples/libs/draco).
|
|
63
|
+
* @param {Object} [config] optional configuration for Draco decoder (see threejs'
|
|
64
|
+
* [setDecoderConfig](https://threejs.org/docs/index.html?q=draco#examples/en/loaders/DRACOLoader.setDecoderConfig) that
|
|
65
|
+
* is called under the hood with this configuration for details.
|
|
66
|
+
*/
|
|
67
|
+
export function enableDracoLoader(path, config) {
|
|
68
|
+
if (!path) {
|
|
69
|
+
throw new Error('Path to draco folder is mandatory');
|
|
70
|
+
}
|
|
71
|
+
const dracoLoader = new DRACOLoader();
|
|
72
|
+
dracoLoader.setDecoderPath(path);
|
|
73
|
+
if (config) {
|
|
74
|
+
dracoLoader.setDecoderConfig(config);
|
|
75
|
+
}
|
|
76
|
+
itownsGLTFLoader.setDRACOLoader(dracoLoader);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Enable loading 3D Tiles with [KTX2](https://www.khronos.org/ktx/) texture extension.
|
|
81
|
+
*
|
|
82
|
+
* @param {String} path path to ktx2 library folder containing the JS and WASM decoder libraries. They can be found in
|
|
83
|
+
* [itowns examples](https://github.com/iTowns/itowns/tree/master/examples/libs/basis).
|
|
84
|
+
* @param {THREE.WebGLRenderer} renderer the threejs renderer
|
|
85
|
+
*/
|
|
86
|
+
export function enableKtx2Loader(path, renderer) {
|
|
87
|
+
if (!path || !renderer) {
|
|
88
|
+
throw new Error('Path to ktx2 folder and renderer are mandatory');
|
|
89
|
+
}
|
|
90
|
+
const ktx2Loader = new KTX2Loader();
|
|
91
|
+
ktx2Loader.setTranscoderPath(path);
|
|
92
|
+
ktx2Loader.detectSupport(renderer);
|
|
93
|
+
itownsGLTFLoader.setKTX2Loader(ktx2Loader);
|
|
94
|
+
}
|
|
95
|
+
class OGC3DTilesLayer extends GeometryLayer {
|
|
96
|
+
/**
|
|
97
|
+
* Layer for [3D Tiles](https://www.ogc.org/standard/3dtiles/) datasets.
|
|
98
|
+
* @extends Layer
|
|
99
|
+
*
|
|
100
|
+
* @constructor
|
|
101
|
+
*
|
|
102
|
+
* @param {String} id - unique layer id.
|
|
103
|
+
* @param {Object} config - layer specific configuration
|
|
104
|
+
* @param {OGC3DTilesSource} config.source - data source configuration
|
|
105
|
+
* @param {String} [config.pntsMode= PNTS_MODE.COLOR] Point cloud coloring mode (passed to {@link PointsMaterial}).
|
|
106
|
+
* Only 'COLOR' or 'CLASSIFICATION' are possible. COLOR uses RGB colors of the points,
|
|
107
|
+
* CLASSIFICATION uses a classification property of the batch table to color points.
|
|
108
|
+
* @param {ClassificationScheme} [config.classificationScheme] {@link PointsMaterial} classification scheme
|
|
109
|
+
* @param {String} [config.pntsShape= PNTS_SHAPE.CIRCLE] Point cloud point shape. Only 'CIRCLE' or 'SQUARE' are possible.
|
|
110
|
+
* (passed to {@link PointsMaterial}).
|
|
111
|
+
* @param {String} [config.pntsSizeMode= PNTS_SIZE_MODE.VALUE] {@link PointsMaterial} Point cloud size mode (passed to {@link PointsMaterial}).
|
|
112
|
+
* Only 'VALUE' or 'ATTENUATED' are possible. VALUE use constant size, ATTENUATED compute size depending on distance
|
|
113
|
+
* from point to camera.
|
|
114
|
+
* @param {Number} [config.pntsMinAttenuatedSize=3] Minimum scale used by 'ATTENUATED' size mode.
|
|
115
|
+
* @param {Number} [config.pntsMaxAttenuatedSize=10] Maximum scale used by 'ATTENUATED' size mode.
|
|
116
|
+
*/
|
|
117
|
+
constructor(id, config) {
|
|
118
|
+
super(id, new THREE.Group(), {
|
|
119
|
+
source: config.source
|
|
120
|
+
});
|
|
121
|
+
this.isOGC3DTilesLayer = true;
|
|
122
|
+
this._handlePointsMaterialConfig(config);
|
|
123
|
+
this.tilesRenderer = new TilesRenderer(this.source.url);
|
|
124
|
+
if (config.source.isOGC3DTilesIonSource) {
|
|
125
|
+
this.tilesRenderer.registerPlugin(new CesiumIonAuthPlugin({
|
|
126
|
+
apiToken: config.source.accessToken,
|
|
127
|
+
assetId: config.source.assetId
|
|
128
|
+
}));
|
|
129
|
+
} else if (config.source.isOGC3DTilesGoogleSource) {
|
|
130
|
+
this.tilesRenderer.registerPlugin(new GoogleCloudAuthPlugin({
|
|
131
|
+
apiToken: config.source.key
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
this.tilesRenderer.registerPlugin(new ImplicitTilingPlugin());
|
|
135
|
+
this.tilesRenderer.manager.addHandler(/\.gltf$/, itownsGLTFLoader);
|
|
136
|
+
this._setupCacheAndQueues();
|
|
137
|
+
this._setupEvents();
|
|
138
|
+
this.object3d.add(this.tilesRenderer.group);
|
|
139
|
+
|
|
140
|
+
// Add an initialization step that is resolved when the root tileset is loaded (see this._setup below), meaning
|
|
141
|
+
// that the layer will be marked ready when the tileset has been loaded.
|
|
142
|
+
this._res = this.addInitializationStep();
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @type {number}
|
|
146
|
+
*/
|
|
147
|
+
this.sseThreshold = this.tilesRenderer.errorTarget;
|
|
148
|
+
Object.defineProperty(this, 'sseThreshold', {
|
|
149
|
+
get() {
|
|
150
|
+
return this.tilesRenderer.errorTarget;
|
|
151
|
+
},
|
|
152
|
+
set(value) {
|
|
153
|
+
this.tilesRenderer.errorTarget = value;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
if (config.sseThreshold) {
|
|
157
|
+
this.sseThreshold = config.sseThreshold;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Store points material config so they can be used later to substitute points tiles material by our own PointsMaterial
|
|
163
|
+
* These properties should eventually be managed through the Style API (see https://github.com/iTowns/itowns/issues/2336)
|
|
164
|
+
* @param {Object} config - points material configuration as passed to the layer constructor.
|
|
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 || 3;
|
|
173
|
+
this.pntsMaxAttenuatedSize = config.pntsMaxAttenuatedSize || 10;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Sets the lruCache and download and parse queues so they are shared amongst all tilesets.
|
|
178
|
+
* @private
|
|
179
|
+
*/
|
|
180
|
+
_setupCacheAndQueues() {
|
|
181
|
+
if (lruCache === null) {
|
|
182
|
+
lruCache = this.tilesRenderer.lruCache;
|
|
183
|
+
} else {
|
|
184
|
+
this.tilesRenderer.lruCache = lruCache;
|
|
185
|
+
}
|
|
186
|
+
if (downloadQueue === null) {
|
|
187
|
+
downloadQueue = this.tilesRenderer.downloadQueue;
|
|
188
|
+
} else {
|
|
189
|
+
this.tilesRenderer.downloadQueue = downloadQueue;
|
|
190
|
+
}
|
|
191
|
+
if (parseQueue === null) {
|
|
192
|
+
parseQueue = this.tilesRenderer.parseQueue;
|
|
193
|
+
} else {
|
|
194
|
+
this.tilesRenderer.parseQueue = parseQueue;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Binds 3d-tiles-renderer events to this layer.
|
|
200
|
+
* @private
|
|
201
|
+
*/
|
|
202
|
+
_setupEvents() {
|
|
203
|
+
for (const ev of Object.values(OGC3DTILES_LAYER_EVENTS)) {
|
|
204
|
+
this.tilesRenderer.addEventListener(ev, e => {
|
|
205
|
+
this.dispatchEvent(e);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Setup 3D tiles renderer js TilesRenderer with the camera, binds events and start updating. Executed when the
|
|
212
|
+
* layer has been added to the view.
|
|
213
|
+
* @param {View} view - the view the layer has been added to.
|
|
214
|
+
* @private
|
|
215
|
+
*/
|
|
216
|
+
_setup(view) {
|
|
217
|
+
this.tilesRenderer.setCamera(view.camera3D);
|
|
218
|
+
this.tilesRenderer.setResolutionFromRenderer(view.camera3D, view.renderer);
|
|
219
|
+
// Setup whenReady to be fullfiled when the root tileset has been loaded
|
|
220
|
+
let rootTilesetLoaded = false;
|
|
221
|
+
this.tilesRenderer.addEventListener('load-tile-set', () => {
|
|
222
|
+
view.notifyChange(this);
|
|
223
|
+
if (!rootTilesetLoaded) {
|
|
224
|
+
rootTilesetLoaded = true;
|
|
225
|
+
this._res();
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
this.tilesRenderer.addEventListener('load-model', _ref => {
|
|
229
|
+
let {
|
|
230
|
+
scene
|
|
231
|
+
} = _ref;
|
|
232
|
+
scene.traverse(obj => {
|
|
233
|
+
this._assignFinalMaterial(obj);
|
|
234
|
+
this._assignFinalAttributes(obj);
|
|
235
|
+
});
|
|
236
|
+
view.notifyChange(this);
|
|
237
|
+
});
|
|
238
|
+
// Start loading tileset and tiles
|
|
239
|
+
this.tilesRenderer.update();
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Replace materials from GLTFLoader by our own custom materials. Note that
|
|
244
|
+
* the replaced materials are not compiled yet and will be disposed by the
|
|
245
|
+
* GC.
|
|
246
|
+
* @param {Object3D} model
|
|
247
|
+
* @private
|
|
248
|
+
*/
|
|
249
|
+
_assignFinalMaterial(model) {
|
|
250
|
+
let material = model.material;
|
|
251
|
+
if (model.isPoints) {
|
|
252
|
+
const pointsMaterial = new PointsMaterial({
|
|
253
|
+
mode: this.pntsMode,
|
|
254
|
+
shape: this.pntsShape,
|
|
255
|
+
classificationScheme: this.classification,
|
|
256
|
+
sizeMode: this.pntsSizeMode,
|
|
257
|
+
minAttenuatedSize: this.pntsMinAttenuatedSize,
|
|
258
|
+
maxAttenuatedSize: this.pntsMaxAttenuatedSize
|
|
259
|
+
});
|
|
260
|
+
pointsMaterial.copy(material);
|
|
261
|
+
material = pointsMaterial;
|
|
262
|
+
}
|
|
263
|
+
if (material) {
|
|
264
|
+
ReferLayerProperties(material, this);
|
|
265
|
+
}
|
|
266
|
+
model.material = material;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* @param {Object3D} model
|
|
271
|
+
* @private
|
|
272
|
+
*/
|
|
273
|
+
_assignFinalAttributes(model) {
|
|
274
|
+
const geometry = model.geometry;
|
|
275
|
+
const batchTable = model.batchTable;
|
|
276
|
+
|
|
277
|
+
// Setup classification bufferAttribute
|
|
278
|
+
if (model.isPoints) {
|
|
279
|
+
const classificationData = batchTable?.getData('Classification');
|
|
280
|
+
if (classificationData) {
|
|
281
|
+
geometry.setAttribute('classification', new THREE.BufferAttribute(classificationData, 1));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
preUpdate() {
|
|
286
|
+
this.tilesRenderer.update();
|
|
287
|
+
return null; // don't return any element because 3d-tiles-renderer already updates them
|
|
288
|
+
}
|
|
289
|
+
update() {
|
|
290
|
+
// empty, elements are updated by 3d-tiles-renderer
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Deletes the layer and frees associated memory
|
|
295
|
+
*/
|
|
296
|
+
delete() {
|
|
297
|
+
this.tilesRenderer.dispose();
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Get the attributes for the closest intersection from a list of
|
|
302
|
+
* intersects.
|
|
303
|
+
* @param {Array} intersects - An array containing all
|
|
304
|
+
* objects picked under mouse coordinates computed with view.pickObjectsAt(..).
|
|
305
|
+
* @returns {Object | null} - An object containing
|
|
306
|
+
*/
|
|
307
|
+
getC3DTileFeatureFromIntersectsArray(intersects) {
|
|
308
|
+
if (!intersects.length) {
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
const {
|
|
312
|
+
face,
|
|
313
|
+
index,
|
|
314
|
+
object
|
|
315
|
+
} = intersects[0];
|
|
316
|
+
|
|
317
|
+
/** @type{number|null} */
|
|
318
|
+
let batchId;
|
|
319
|
+
if (object.isPoints && index) {
|
|
320
|
+
batchId = object.geometry.getAttribute('_BATCHID')?.getX(index) ?? index;
|
|
321
|
+
} else if (object.isMesh && face) {
|
|
322
|
+
batchId = object.geometry.getAttribute('_BATCHID')?.getX(face.a);
|
|
323
|
+
}
|
|
324
|
+
if (batchId === undefined) {
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
let tileObject = object;
|
|
328
|
+
while (!tileObject.batchTable) {
|
|
329
|
+
tileObject = tileObject.parent;
|
|
330
|
+
}
|
|
331
|
+
return tileObject.batchTable.getDataFromId(batchId);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Get all 3D objects (mesh and points primitives) as intersects at the
|
|
336
|
+
* given non-normalized screen coordinates.
|
|
337
|
+
* @param {View} view - The view instance.
|
|
338
|
+
* @param {THREE.Vector2} coords - The coordinates to pick in the view. It
|
|
339
|
+
* should have at least `x` and `y` properties.
|
|
340
|
+
* @param {number} radius - Radius of the picking circle.
|
|
341
|
+
* @param {Array} [target=[]] - Target array to push results too
|
|
342
|
+
* @returns {Array} Array containing all target objects picked under the
|
|
343
|
+
* specified coordinates.
|
|
344
|
+
*/
|
|
345
|
+
pickObjectsAt(view, coords) {
|
|
346
|
+
let target = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
|
|
347
|
+
const camera = view.camera.camera3D;
|
|
348
|
+
_raycaster.setFromCamera(view.viewToNormalizedCoords(coords), camera);
|
|
349
|
+
_raycaster.near = camera.near;
|
|
350
|
+
_raycaster.far = camera.far;
|
|
351
|
+
_raycaster.firstHitOnly = true;
|
|
352
|
+
_raycaster.intersectObject(this.tilesRenderer.group, true, target);
|
|
353
|
+
return target;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// eslint-disable-next-line no-unused-vars
|
|
357
|
+
attach() {
|
|
358
|
+
console.warn('[OGC3DTilesLayer]: Attaching / detaching layers is not yet implemented for OGC3DTilesLayer.');
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// eslint-disable-next-line no-unused-vars
|
|
362
|
+
detach() {
|
|
363
|
+
console.warn('[OGC3DTilesLayer]: Attaching / detaching layers is not yet implemented for OGC3DTilesLayer.');
|
|
364
|
+
return true;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// eslint-disable-next-line no-unused-vars
|
|
368
|
+
getObjectToUpdateForAttachedLayers() {
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Executes a callback for each tile of this layer tileset.
|
|
374
|
+
*
|
|
375
|
+
* @param {Function} callback The callback to execute for each tile. Has the following two parameters:
|
|
376
|
+
* 1. tile (Object) - the JSON tile
|
|
377
|
+
* 2. scene (THREE.Object3D | null) - The tile content. Contains a `batchTable` property. Can be null if the tile
|
|
378
|
+
* has not yet been loaded.
|
|
379
|
+
*/
|
|
380
|
+
forEachTile(callback) {
|
|
381
|
+
this.tilesRenderer.traverse(tile => {
|
|
382
|
+
callback(tile, tile.cached.scene);
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
export default OGC3DTilesLayer;
|
package/lib/Main.js
CHANGED
|
@@ -53,6 +53,7 @@ export { default as PointCloudLayer } from "./Layer/PointCloudLayer.js";
|
|
|
53
53
|
export { default as PotreeLayer } from "./Layer/PotreeLayer.js";
|
|
54
54
|
export { default as Potree2Layer } from "./Layer/Potree2Layer.js";
|
|
55
55
|
export { default as C3DTilesLayer, C3DTILES_LAYER_EVENTS } from "./Layer/C3DTilesLayer.js";
|
|
56
|
+
export { default as OGC3DTilesLayer, OGC3DTILES_LAYER_EVENTS, enableDracoLoader, enableKtx2Loader } from "./Layer/OGC3DTilesLayer.js";
|
|
56
57
|
export { default as TiledGeometryLayer } from "./Layer/TiledGeometryLayer.js";
|
|
57
58
|
export { default as OrientedImageLayer } from "./Layer/OrientedImageLayer.js";
|
|
58
59
|
export { STRATEGY_MIN_NETWORK_TRAFFIC, STRATEGY_GROUP, STRATEGY_PROGRESSIVE, STRATEGY_DICHOTOMY } from "./Layer/LayerUpdateStrategy.js";
|
|
@@ -80,6 +81,9 @@ export { default as Potree2Source } from "./Source/Potree2Source.js";
|
|
|
80
81
|
export { default as C3DTilesSource } from "./Source/C3DTilesSource.js";
|
|
81
82
|
export { default as C3DTilesIonSource } from "./Source/C3DTilesIonSource.js";
|
|
82
83
|
export { default as C3DTilesGoogleSource } from "./Source/C3DTilesGoogleSource.js";
|
|
84
|
+
export { default as OGC3DTilesSource } from "./Source/OGC3DTilesSource.js";
|
|
85
|
+
export { default as OGC3DTilesIonSource } from "./Source/OGC3DTilesIonSource.js";
|
|
86
|
+
export { default as OGC3DTilesGoogleSource } from "./Source/OGC3DTilesGoogleSource.js";
|
|
83
87
|
export { default as EntwinePointTileSource } from "./Source/EntwinePointTileSource.js";
|
|
84
88
|
export { default as CopcSource } from "./Source/CopcSource.js";
|
|
85
89
|
|
|
@@ -95,7 +99,8 @@ export { default as LASParser } from "./Parser/LASParser.js";
|
|
|
95
99
|
export { default as ISGParser } from "./Parser/ISGParser.js";
|
|
96
100
|
export { default as GDFParser } from "./Parser/GDFParser.js";
|
|
97
101
|
export { default as GTXParser } from "./Parser/GTXParser.js";
|
|
98
|
-
export { default as
|
|
102
|
+
export { default as B3dmParser } from "./Parser/B3dmParser.js";
|
|
103
|
+
export { default as iGLTFLoader } from "./Parser/iGLTFLoader.js";
|
|
99
104
|
|
|
100
105
|
// 3D Tiles classes and extensions
|
|
101
106
|
// Exported to allow one to implement its own 3D Tiles extension which needs to
|
package/lib/Parser/B3dmParser.js
CHANGED
|
@@ -5,8 +5,10 @@ import { MeshBasicMaterial } from 'three';
|
|
|
5
5
|
import disposeThreeMaterial from "../Utils/ThreeUtils.js";
|
|
6
6
|
import shaderUtils from "../Renderer/Shader/ShaderUtils.js";
|
|
7
7
|
import ReferLayerProperties from "../Layer/ReferencingLayerProperties.js";
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
// A bit weird but temporary until we remove this deprecated parser. Mainly to benefit from the enableDracoLoader and enableKtx2Loader
|
|
9
|
+
// methods.
|
|
10
|
+
import { itownsGLTFLoader } from "../Layer/OGC3DTilesLayer.js";
|
|
11
|
+
const matrixChangeUpVectorYtoZ = new THREE.Matrix4().makeRotationX(Math.PI / 2);
|
|
10
12
|
const matrixChangeUpVectorXtoZ = new THREE.Matrix4().makeRotationZ(-Math.PI / 2);
|
|
11
13
|
const utf8Decoder = new TextDecoder();
|
|
12
14
|
|
|
@@ -34,18 +36,15 @@ function filterUnsupportedSemantics(obj) {
|
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* gltf file to have it z-up in the end).
|
|
39
|
+
* Transforms loaded gltf model to z-up (either from y-up or from the up axis defined in gltfUpAxis). Note that
|
|
40
|
+
* gltfUpAxis was an attribut of pre-1.0 3D Tiles and is now deprecated.
|
|
40
41
|
* @param {THREE.Object3D} gltfScene - the parsed glTF scene
|
|
41
42
|
* @param {String} gltfUpAxis - the gltfUpAxis parameter
|
|
42
43
|
*/
|
|
43
|
-
function
|
|
44
|
-
if (gltfUpAxis === '
|
|
45
|
-
|
|
46
|
-
gltfScene.applyMatrix4(matrixChangeUpVectorYtoZInv);
|
|
44
|
+
function transformToZUp(gltfScene, gltfUpAxis) {
|
|
45
|
+
if (!gltfUpAxis || gltfUpAxis === 'Y') {
|
|
46
|
+
gltfScene.applyMatrix4(matrixChangeUpVectorYtoZ);
|
|
47
47
|
} else if (gltfUpAxis === 'X') {
|
|
48
|
-
gltfScene.applyMatrix4(matrixChangeUpVectorYtoZInv);
|
|
49
48
|
gltfScene.applyMatrix4(matrixChangeUpVectorXtoZ);
|
|
50
49
|
}
|
|
51
50
|
}
|
|
@@ -127,7 +126,6 @@ export default {
|
|
|
127
126
|
}
|
|
128
127
|
const posGltf = headerByteLength + b3dmHeader.FTJSONLength + b3dmHeader.FTBinaryLength + b3dmHeader.BTJSONLength + b3dmHeader.BTBinaryLength;
|
|
129
128
|
const gltfBuffer = buffer.slice(posGltf);
|
|
130
|
-
const headerView = new DataView(gltfBuffer, 0, 20);
|
|
131
129
|
const init_mesh = function (mesh) {
|
|
132
130
|
mesh.frustumCulled = frustumCulled;
|
|
133
131
|
if (mesh.material) {
|
|
@@ -147,11 +145,11 @@ export default {
|
|
|
147
145
|
ReferLayerProperties(mesh.material, options.layer);
|
|
148
146
|
}
|
|
149
147
|
};
|
|
150
|
-
promises.push(
|
|
148
|
+
promises.push(itownsGLTFLoader.parseAsync(gltfBuffer, options).then(gltf => {
|
|
151
149
|
for (const scene of gltf.scenes) {
|
|
152
150
|
scene.traverse(filterUnsupportedSemantics);
|
|
153
151
|
}
|
|
154
|
-
|
|
152
|
+
transformToZUp(gltf.scene, options.gltfUpAxis);
|
|
155
153
|
const shouldBePatchedForLogDepthSupport = Capabilities.isLogDepthBufferSupported() && !options.doNotPatchMaterial;
|
|
156
154
|
if (options.frustumCulling === false || options.overrideMaterials || shouldBePatchedForLogDepthSupport || options.layer) {
|
|
157
155
|
gltf.scene.traverse(init_mesh);
|
|
@@ -159,15 +157,6 @@ export default {
|
|
|
159
157
|
|
|
160
158
|
// Apply relative center from Feature table.
|
|
161
159
|
gltf.scene.position.copy(FT_RTC);
|
|
162
|
-
|
|
163
|
-
// Apply relative center from gltf json.
|
|
164
|
-
const contentArray = new Uint8Array(gltfBuffer, 20, headerView.getUint32(12, true));
|
|
165
|
-
const content = utf8Decoder.decode(new Uint8Array(contentArray));
|
|
166
|
-
const json = JSON.parse(content);
|
|
167
|
-
if (json.extensions && json.extensions.CESIUM_RTC) {
|
|
168
|
-
gltf.scene.position.fromArray(json.extensions.CESIUM_RTC.center);
|
|
169
|
-
gltf.scene.updateMatrixWorld(true);
|
|
170
|
-
}
|
|
171
160
|
return gltf;
|
|
172
161
|
}).catch(e => {
|
|
173
162
|
throw new Error(e);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
|
-
//
|
|
2
|
+
// LegacyGLTFLoader for loading gltf 1.0 files taken from THREE v110 because it was removed in THREE v111 and maintained
|
|
3
|
+
// since
|
|
3
4
|
import * as THREE from 'three';
|
|
4
5
|
const threeExamples = {};
|
|
5
6
|
/**
|
|
@@ -45,6 +46,9 @@ threeExamples.LegacyGLTFLoader = function () {
|
|
|
45
46
|
if (json.extensionsUsed && json.extensionsUsed.indexOf(EXTENSIONS.KHR_MATERIALS_COMMON) >= 0) {
|
|
46
47
|
extensions[EXTENSIONS.KHR_MATERIALS_COMMON] = new GLTFMaterialsCommonExtension(json);
|
|
47
48
|
}
|
|
49
|
+
if (json.extensionsUsed && json.extensionsUsed.indexOf(EXTENSIONS.CESIUM_RTC) >= 0) {
|
|
50
|
+
extensions[EXTENSIONS.CESIUM_RTC] = new CesiumRTCExtension(json);
|
|
51
|
+
}
|
|
48
52
|
var parser = new GLTFParser(json, extensions, {
|
|
49
53
|
crossOrigin: this.crossOrigin,
|
|
50
54
|
manager: this.manager,
|
|
@@ -175,7 +179,8 @@ threeExamples.LegacyGLTFLoader = function () {
|
|
|
175
179
|
|
|
176
180
|
var EXTENSIONS = {
|
|
177
181
|
KHR_BINARY_GLTF: 'KHR_binary_glTF',
|
|
178
|
-
KHR_MATERIALS_COMMON: 'KHR_materials_common'
|
|
182
|
+
KHR_MATERIALS_COMMON: 'KHR_materials_common',
|
|
183
|
+
CESIUM_RTC: 'CESIUM_RTC'
|
|
179
184
|
};
|
|
180
185
|
|
|
181
186
|
/* MATERIALS COMMON EXTENSION */
|
|
@@ -247,6 +252,17 @@ threeExamples.LegacyGLTFLoader = function () {
|
|
|
247
252
|
return THREE.LoaderUtils.decodeText(array);
|
|
248
253
|
};
|
|
249
254
|
|
|
255
|
+
// Ref spec https://github.com/KhronosGroup/glTF/blob/main/extensions/1.0/Vendor/CESIUM_RTC/README.md
|
|
256
|
+
// Only the json storage method is implemented since it is the only one we've seen out there and since this extension
|
|
257
|
+
// is specific to deprecated 3D tiles with GLTF 1.0
|
|
258
|
+
function CesiumRTCExtension(json) {
|
|
259
|
+
this.name = EXTENSIONS.CESIUM_RTC;
|
|
260
|
+
this.center = [0, 0, 0];
|
|
261
|
+
if (json.extensions && json.extensions[EXTENSIONS.CESIUM_RTC] && json.extensions[EXTENSIONS.CESIUM_RTC].center && json.extensions[EXTENSIONS.CESIUM_RTC].center.length === 3) {
|
|
262
|
+
this.center = json.extensions[EXTENSIONS.CESIUM_RTC].center;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
250
266
|
/*********************************/
|
|
251
267
|
/********** INTERNALS ************/
|
|
252
268
|
/*********************************/
|
|
@@ -526,9 +542,9 @@ threeExamples.LegacyGLTFLoader = function () {
|
|
|
526
542
|
}
|
|
527
543
|
|
|
528
544
|
/**
|
|
529
|
-
* Verifies if the shaders are Cesium specific: if they contain attributes, uniforms or functions starting with
|
|
530
|
-
* `czm_`. The cesium gltf-pipeline (the ancestor of cesium ion) used to create 3D Tiles tilesets they are only
|
|
531
|
-
* defined in Cesium.
|
|
545
|
+
* Verifies if the shaders are Cesium specific: if they contain attributes, uniforms or functions starting with
|
|
546
|
+
* `czm_`. The cesium gltf-pipeline (the ancestor of cesium ion) used to create 3D Tiles tilesets they are only
|
|
547
|
+
* defined in Cesium.
|
|
532
548
|
* @param {Object} shaders
|
|
533
549
|
*/
|
|
534
550
|
function areShadersCesiumSpecific(shaders) {
|
|
@@ -1323,6 +1339,7 @@ threeExamples.LegacyGLTFLoader = function () {
|
|
|
1323
1339
|
};
|
|
1324
1340
|
GLTFParser.prototype.loadScenes = function () {
|
|
1325
1341
|
var json = this.json;
|
|
1342
|
+
var extensions = this.extensions;
|
|
1326
1343
|
|
|
1327
1344
|
// scene node hierachy builder
|
|
1328
1345
|
|
|
@@ -1357,6 +1374,9 @@ threeExamples.LegacyGLTFLoader = function () {
|
|
|
1357
1374
|
};
|
|
1358
1375
|
}
|
|
1359
1376
|
});
|
|
1377
|
+
if (extensions[EXTENSIONS.CESIUM_RTC]) {
|
|
1378
|
+
_scene.position.fromArray(extensions[EXTENSIONS.CESIUM_RTC].center);
|
|
1379
|
+
}
|
|
1360
1380
|
return _scene;
|
|
1361
1381
|
});
|
|
1362
1382
|
});
|