@jdultra/threedtiles 7.0.1 → 8.0.0

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.
@@ -4,12 +4,14 @@ import { TileLoader } from "./TileLoader";
4
4
  import { v4 as uuidv4 } from "uuid";
5
5
  import * as path from "path-browserify"
6
6
  import { clamp } from "three/src/math/MathUtils";
7
+ import { Octree } from 'three/addons/math/Octree.js';
8
+ import { OctreeHelper } from 'three/addons/helpers/OctreeHelper.js';
7
9
 
8
10
  const tempSphere = new THREE.Sphere(new THREE.Vector3(0, 0, 0), 1);
9
11
  const tempVec1 = new THREE.Vector3(0, 0, 0);
10
12
  const tempVec2 = new THREE.Vector3(0, 0, 0);
11
13
  const upVector = new THREE.Vector3(0, 1, 0);
12
- const rendererSize = new THREE.Vector2(1000,1000);
14
+ const rendererSize = new THREE.Vector2(1000, 1000);
13
15
  const tempQuaternion = new THREE.Quaternion();
14
16
 
15
17
 
@@ -46,16 +48,16 @@ class OGC3DTile extends THREE.Object3D {
46
48
  if (!!properties.tileLoader) {
47
49
  this.tileLoader = properties.tileLoader;
48
50
  } else {
49
- this.tileLoader = new TileLoader(
50
- 200,
51
- !properties.meshCallback ? mesh => {
52
- mesh.material.wireframe = false;
53
- mesh.material.side = THREE.DoubleSide;
54
- } : properties.meshCallback,
55
- !properties.pointsCallback ? points => {
56
- points.material.size = 0.1;
57
- points.material.sizeAttenuation = true;
58
- } : properties.pointsCallback);
51
+ const tileLoaderOptions = {};
52
+ tileLoaderOptions.meshCallback = !properties.meshCallback ? mesh => {
53
+ mesh.material.wireframe = false;
54
+ mesh.material.side = THREE.DoubleSide;
55
+ } : properties.meshCallback;
56
+ tileLoaderOptions.pointsCallback = !properties.pointsCallback ? points => {
57
+ points.material.size = 0.1;
58
+ points.material.sizeAttenuation = true;
59
+ } : properties.pointsCallback;
60
+ this.tileLoader = new TileLoader(tileLoaderOptions);
59
61
  }
60
62
  // set properties general to the entire tileset
61
63
  this.geometricErrorMultiplier = !!properties.geometricErrorMultiplier ? properties.geometricErrorMultiplier : 1.0;
@@ -93,6 +95,7 @@ class OGC3DTile extends THREE.Object3D {
93
95
  this.centerModel = properties.centerModel;
94
96
  this.abortController = new AbortController();
95
97
  this.layers.disable(0);
98
+ this.octree = new Octree();
96
99
 
97
100
  if (!!properties.json) { // If this tile is created as a child of another tile, properties.json is not null
98
101
  self.setup(properties);
@@ -123,11 +126,11 @@ class OGC3DTile extends THREE.Object3D {
123
126
  (this.json.boundingVolume.region[1] + this.json.boundingVolume.region[3]) * 0.5,
124
127
  (this.json.boundingVolume.region[4] + this.json.boundingVolume.region[5]) * 0.5,
125
128
  tempVec1);
126
-
129
+
127
130
  tempQuaternion.setFromUnitVectors(tempVec1.normalize(), upVector.normalize());
128
131
  self.applyQuaternion(tempQuaternion);
129
132
  }
130
-
133
+
131
134
  self.translateX(-tempSphere.center.x * self.scale.x);
132
135
  self.translateY(-tempSphere.center.y * self.scale.y);
133
136
  self.translateZ(-tempSphere.center.z * self.scale.z);
@@ -169,7 +172,7 @@ class OGC3DTile extends THREE.Object3D {
169
172
  mat.elements = this.json.transform;
170
173
  this.applyMatrix4(mat);
171
174
  }
172
-
175
+
173
176
  // decode volume
174
177
  if (!!this.json.boundingVolume) {
175
178
  if (!!this.json.boundingVolume.box) {
@@ -190,7 +193,7 @@ class OGC3DTile extends THREE.Object3D {
190
193
  this.boundingVolume = properties.parentBoundingVolume;
191
194
  }
192
195
 
193
-
196
+
194
197
 
195
198
  if (!!this.json.content) { //if there is a content, json or otherwise, schedule it to be loaded
196
199
  if (!!this.json.content.uri && this.json.content.uri.includes("json")) {
@@ -204,19 +207,31 @@ class OGC3DTile extends THREE.Object3D {
204
207
  //scheduleLoadTile(this);
205
208
  }
206
209
  }
210
+
211
+ isAbsolutePathOrURL(input) {
212
+ // Check if it's an absolute URL with various protocols
213
+ const urlRegex = /^(?:http|https|ftp|tcp|udp):\/\/\S+/;
214
+ const absoluteURL = urlRegex.test(input);
215
+
216
+ // Check if it's an absolute path
217
+ const absolutePath = input.startsWith('/') && !input.startsWith('//');
218
+
219
+ return absoluteURL || absolutePath;
220
+ }
221
+
207
222
  load() {
208
223
  var self = this;
209
224
  if (self.deleted) return;
210
225
  if (!!self.json.content) {
211
226
  let url;
212
227
  if (!!self.json.content.uri) {
213
- if (path.isAbsolute(self.json.content.uri)) {
228
+ if (path.isAbsolute(self.json.content.uri) || self.isAbsolutePathOrURL(self.json.content.uri)) {
214
229
  url = self.json.content.uri;
215
230
  } else {
216
231
  url = self.rootPath + path.sep + self.json.content.uri;
217
232
  }
218
233
  } else if (!!self.json.content.url) {
219
- if (path.isAbsolute(self.json.content.url)) {
234
+ if (path.isAbsolute(self.json.content.url) || self.isAbsolutePathOrURL(self.json.content.url)) {
220
235
  url = self.json.content.url;
221
236
  } else {
222
237
  url = self.rootPath + path.sep + self.json.content.url;
@@ -226,12 +241,12 @@ class OGC3DTile extends THREE.Object3D {
226
241
  if (!!url) {
227
242
  if (url.includes(".b3dm") || url.includes(".glb") || url.includes(".gltf")) {
228
243
  self.contentURL = url;
229
-
244
+
230
245
  self.tileLoader.get(self.abortController, this.uuid, url, mesh => {
231
246
  if (!!self.deleted) return;
232
247
  mesh.traverse((o) => {
233
248
  if (o.isMesh) {
234
-
249
+
235
250
  o.layers.disable(0);
236
251
  if (self.occlusionCullingService) {
237
252
  const position = o.geometry.attributes.position;
@@ -247,17 +262,19 @@ class OGC3DTile extends THREE.Object3D {
247
262
  //o.material.visible = false;
248
263
  }
249
264
  });
250
-
265
+ //let s = Date.now();
266
+ //self.octree.fromGraphNode( mesh );
267
+ //console.log(Date.now()-s);
251
268
  self.add(mesh);
252
269
  self.updateWorldMatrix(false, true);
253
270
  // mesh.layers.disable(0);
254
271
  self.meshContent = mesh;
255
272
  }, !self.cameraOnLoad ? () => 0 : () => {
256
273
  return self.calculateDistanceToCamera(self.cameraOnLoad);
257
- }, () => self.getSiblings(),
258
- self.level,
259
- !!self.json.boundingVolume.region,
260
- self.geometricError
274
+ }, () => self.getSiblings(),
275
+ self.level,
276
+ !!self.json.boundingVolume.region,
277
+ self.geometricError
261
278
  );
262
279
  } else if (url.includes(".json")) {
263
280
  self.tileLoader.get(self.abortController, this.uuid, url, json => {
@@ -537,7 +554,7 @@ class OGC3DTile extends THREE.Object3D {
537
554
  return;
538
555
  }
539
556
  self.materialVisibility = visibility
540
-
557
+
541
558
  self.meshDisplayed = true;
542
559
  if (!!self.meshContent.traverse) {
543
560
  self.meshContent.traverse(function (element) {
@@ -585,7 +602,7 @@ class OGC3DTile extends THREE.Object3D {
585
602
  return 0;
586
603
  }
587
604
  const scale = this.matrixWorld.getMaxScaleOnAxis();
588
- if(!!this.renderer){
605
+ if (!!this.renderer) {
589
606
  this.renderer.getDrawingBufferSize(rendererSize);
590
607
  }
591
608
  let s = rendererSize.y;
@@ -5,6 +5,7 @@ import { initial } from 'lodash';
5
5
  import * as THREE from 'three';
6
6
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
7
7
  import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
8
+ import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader";
8
9
 
9
10
  let concurentDownloads = 0;
10
11
  const zUpToYUpMatrix = new THREE.Matrix4();
@@ -12,17 +13,49 @@ zUpToYUpMatrix.set(1, 0, 0, 0,
12
13
  0, 0, -1, 0,
13
14
  0, 1, 0, 0,
14
15
  0, 0, 0, 1);
15
- const gltfLoader = new GLTFLoader();
16
- const dracoLoader = new DRACOLoader();
17
- dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.4.3/');
18
- gltfLoader.setDRACOLoader(dracoLoader);
19
16
 
17
+
18
+
19
+
20
+ /**
21
+ * A Tile loader that manages caching and load order.
22
+ * The cache is an LRU cache and is defined by the number of items it can hold.
23
+ * The actual number of cached items might grow beyond max if all items are in use.
24
+ *
25
+ * The load order is designed for optimal perceived loading speed (nearby tiles are refined first).
26
+ *
27
+ * @param {Object} [options] - Optional configuration object.
28
+ * @param {number} [options.maxCachedItems=100] - the cache size.
29
+ * @param {function} [options.meshCallback] - A callback to call on newly decoded meshes.
30
+ * @param {function} [options.pointsCallback] - A callback to call on newly decoded points.
31
+ * @param {renderer} [options.renderer] - The renderer, this is required for KTX2 support.
32
+ */
20
33
  class TileLoader {
21
- constructor(maxCachedItems, meshCallback, pointsCallback) {
22
- this.meshCallback = meshCallback;
23
- this.pointsCallback = pointsCallback;
34
+ constructor(options) {
35
+ this.maxCachedItems = 100;
36
+ if (!!options) {
37
+ this.meshCallback = options.meshCallback;
38
+ this.pointsCallback = options.pointsCallback;
39
+ if (options.maxCachedItems) this.maxCachedItems = options.maxCachedItems;
40
+
41
+ }
42
+
43
+ this.gltfLoader = new GLTFLoader();
44
+ const dracoLoader = new DRACOLoader();
45
+ dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.4.3/');
46
+ this.gltfLoader.setDRACOLoader(dracoLoader);
47
+
48
+ if(!!options && !!options.renderer){
49
+ const ktx2Loader = new KTX2Loader();
50
+ ktx2Loader.setTranscoderPath('https://storage.googleapis.com/ogc-3d-tiles/basis/').detectSupport(options.renderer);
51
+ this.gltfLoader.setKTX2Loader(ktx2Loader);
52
+
53
+ this.b3dmDecoder=new B3DMDecoder(options.renderer);
54
+ }else{
55
+ this.b3dmDecoder=new B3DMDecoder(null);
56
+ }
57
+
24
58
  this.cache = new LinkedHashMap();
25
- this.maxCachedItems = !!maxCachedItems ? maxCachedItems : 100;
26
59
  this.register = {};
27
60
 
28
61
 
@@ -33,6 +66,7 @@ class TileLoader {
33
66
  this.init();
34
67
  }
35
68
 
69
+
36
70
  init() {
37
71
 
38
72
  const self = this;
@@ -195,7 +229,7 @@ class TileLoader {
195
229
 
196
230
  })
197
231
  .then(resultArrayBuffer => {
198
- return B3DMDecoder.parseB3DM(resultArrayBuffer, self.meshCallback, geometricError, zUpToYUp);
232
+ return this.b3dmDecoder.parseB3DM(resultArrayBuffer, self.meshCallback, geometricError, zUpToYUp);
199
233
  })
200
234
  .then(mesh => {
201
235
  self.cache.put(key, mesh);
@@ -207,7 +241,7 @@ class TileLoader {
207
241
  } else if (path.includes(".glb") || path.includes(".gltf")) {
208
242
  downloadFunction = () => {
209
243
  concurentDownloads++;
210
- gltfLoader.load(path, gltf => {
244
+ this.gltfLoader.load(path, gltf => {
211
245
  gltf.scene.traverse((o) => {
212
246
  o.geometricError = geometricError;
213
247
  if (o.isMesh) {
@@ -193,19 +193,30 @@ class InstancedTile extends THREE.Object3D {
193
193
  //scheduleLoadTile(this);
194
194
  }
195
195
  }
196
+
197
+ isAbsolutePathOrURL(input) {
198
+ // Check if it's an absolute URL with various protocols
199
+ const urlRegex = /^(?:http|https|ftp|tcp|udp):\/\/\S+/;
200
+ const absoluteURL = urlRegex.test(input);
201
+
202
+ // Check if it's an absolute path
203
+ const absolutePath = input.startsWith('/') && !input.startsWith('//');
204
+
205
+ return absoluteURL || absolutePath;
206
+ }
196
207
  load() {
197
208
  var self = this;
198
209
  if (self.deleted) return;
199
210
  if (!!self.json.content) {
200
211
  let url;
201
212
  if (!!self.json.content.uri) {
202
- if (path.isAbsolute(self.json.content.uri)) {
213
+ if (path.isAbsolute(self.json.content.uri) || self.isAbsolutePathOrURL(self.json.content.uri)) {
203
214
  url = self.json.content.uri;
204
215
  } else {
205
216
  url = self.rootPath + path.sep + self.json.content.uri;
206
217
  }
207
218
  } else if (!!self.json.content.url) {
208
- if (path.isAbsolute(self.json.content.url)) {
219
+ if (path.isAbsolute(self.json.content.url) || self.isAbsolutePathOrURL(self.json.content.url)) {
209
220
  url = self.json.content.url;
210
221
  } else {
211
222
  url = self.rootPath + path.sep + self.json.content.url;
@@ -356,7 +367,7 @@ class InstancedTile extends THREE.Object3D {
356
367
  }
357
368
  if (metric >= self.master.geometricErrorMultiplier * self.geometricError) {
358
369
  self.disposeChildren();
359
- updateNodeVisibility();
370
+ updateNodeVisibility(metric);
360
371
  return;
361
372
  }
362
373
 
@@ -6,25 +6,58 @@ import { MeshTile } from './MeshTile';
6
6
  import { JsonTile } from './JsonTile';
7
7
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
8
8
  import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
9
-
9
+ import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader";
10
10
 
11
11
  let concurentDownloads = 0;
12
- const gltfLoader = new GLTFLoader();
13
- const dracoLoader = new DRACOLoader();
14
- dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.4.3/');
15
- gltfLoader.setDRACOLoader(dracoLoader);
12
+
16
13
  const zUpToYUpMatrix = new THREE.Matrix4();
17
14
  zUpToYUpMatrix.set(1, 0, 0, 0,
18
15
  0, 0, -1, 0,
19
16
  0, 1, 0, 0,
20
17
  0, 0, 0, 1);
21
18
 
19
+ /**
20
+ * A Tile loader that manages caching and load order for instanced tiles.
21
+ * The cache is an LRU cache and is defined by the number of items it can hold.
22
+ * The actual number of cached items might grow beyond max if all items are in use.
23
+ *
24
+ * The load order is designed for optimal perceived loading speed (nearby tiles are refined first).
25
+ *
26
+ * @param {scene} [scene] - a threejs scene.
27
+ * @param {Object} [options] - Optional configuration object.
28
+ * @param {number} [options.maxCachedItems=100] - the cache size.
29
+ * @param {number} [options.maxInstances=1] - the cache size.
30
+ * @param {function} [options.meshCallback] - A callback to call on newly decoded meshes.
31
+ * @param {function} [options.pointsCallback] - A callback to call on newly decoded points.
32
+ * @param {renderer} [options.renderer] - The renderer, this is required for KTX2 support.
33
+ */
22
34
  class InstancedTileLoader {
23
- constructor(scene, maxCachedItems, maxInstances, meshCallback) {
24
- this.meshCallback = meshCallback;
25
- this.maxInstances = maxInstances;
35
+ constructor(scene, options) {
36
+ this.maxCachedItems = 100;
37
+ this.maxInstances = 1;
38
+ if (!!options) {
39
+ this.meshCallback = options.meshCallback;
40
+ this.pointsCallback = options.pointsCallback;
41
+ if (options.maxCachedItems) this.maxCachedItems = options.maxCachedItems;
42
+ if (options.maxInstances) this.maxInstances = options.maxInstances;
43
+
44
+ }
45
+ this.gltfLoader = new GLTFLoader();
46
+ const dracoLoader = new DRACOLoader();
47
+ dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.4.3/');
48
+ this.gltfLoader.setDRACOLoader(dracoLoader);
49
+
50
+ if(!!options && !!options.renderer){
51
+ const ktx2Loader = new KTX2Loader();
52
+ ktx2Loader.setTranscoderPath('https://storage.googleapis.com/ogc-3d-tiles/basis/').detectSupport(options.renderer);
53
+ this.gltfLoader.setKTX2Loader(ktx2Loader);
54
+
55
+ this.b3dmDecoder=new B3DMDecoder(options.renderer);
56
+ }else{
57
+ this.b3dmDecoder=new B3DMDecoder(null);
58
+ }
59
+
26
60
  this.cache = new LinkedHashMap();
27
- this.maxCachedItems = !!maxCachedItems ? maxCachedItems : 100;
28
61
  this.scene = scene;
29
62
 
30
63
  this.ready = [];
@@ -34,16 +67,17 @@ class InstancedTileLoader {
34
67
  this.init();
35
68
  }
36
69
 
37
- update(){
70
+
71
+ update() {
38
72
  const self = this;
39
-
40
- self.cache._data.forEach(v=>{
73
+
74
+ self.cache._data.forEach(v => {
41
75
  v.update();
42
76
  })
43
-
77
+
44
78
  }
45
- init(){
46
-
79
+ init() {
80
+
47
81
  const self = this;
48
82
  setIntervalAsync(() => {
49
83
  self.download();
@@ -54,7 +88,7 @@ class InstancedTileLoader {
54
88
  do {
55
89
  loaded = self.loadBatch();
56
90
  } while (loaded > 0 && (Date.now() - start) <= 0)
57
-
91
+
58
92
  }, 10);
59
93
  }
60
94
 
@@ -69,8 +103,8 @@ class InstancedTileLoader {
69
103
  if (!!nextDownload && nextDownload.shouldDoDownload()) {
70
104
  //nextDownload.doDownload();
71
105
  concurentDownloads++;
72
- if(nextDownload.path.includes(".b3dm")){
73
- fetch(nextDownload.path, {signal: nextDownload.abortController.signal}).then(result => {
106
+ if (nextDownload.path.includes(".b3dm")) {
107
+ fetch(nextDownload.path, { signal: nextDownload.abortController.signal }).then(result => {
74
108
  concurentDownloads--;
75
109
  if (!result.ok) {
76
110
  console.error("could not load tile with path : " + path)
@@ -79,17 +113,17 @@ class InstancedTileLoader {
79
113
  return result.arrayBuffer();
80
114
 
81
115
  })
82
- .then(resultArrayBuffer=>{
83
- return B3DMDecoder.parseB3DMInstanced(resultArrayBuffer, self.meshCallback, self.maxInstances, nextDownload.zUpToYUp);
84
- })
85
- .then(mesh=>{
86
- nextDownload.tile.setObject(mesh);
87
- self.ready.unshift(nextDownload);
88
-
89
- })
90
- .catch(e=>console.error(e));
91
- }if(nextDownload.path.includes(".glb") || (nextDownload.path.includes(".gltf"))){
92
- gltfLoader.load(nextDownload.path, gltf => {
116
+ .then(resultArrayBuffer => {
117
+ return this.b3dmDecoder.parseB3DMInstanced(resultArrayBuffer, self.meshCallback, self.maxInstances, nextDownload.zUpToYUp);
118
+ })
119
+ .then(mesh => {
120
+ nextDownload.tile.setObject(mesh);
121
+ self.ready.unshift(nextDownload);
122
+
123
+ })
124
+ .catch(e => console.error(e));
125
+ } if (nextDownload.path.includes(".glb") || (nextDownload.path.includes(".gltf"))) {
126
+ this.gltfLoader.load(nextDownload.path, gltf => {
93
127
  gltf.scene.traverse((o) => {
94
128
  o.geometricError = nextDownload.geometricError;
95
129
  if (o.isMesh) {
@@ -112,34 +146,34 @@ class InstancedTileLoader {
112
146
  instancedMesh = new THREE.InstancedMesh(child.geometry, child.material, self.maxInstances);
113
147
  instancedMesh.baseMatrix = child.matrixWorld;
114
148
  }
115
-
149
+
116
150
  });
117
151
  self.ready.unshift(nextDownload);
118
- if(!instancedMesh){
119
- gltf.scene.traverse(c=>{
120
- if(c.dispose) c.dispose();
121
- if(c.material) c.material.dispose();
152
+ if (!instancedMesh) {
153
+ gltf.scene.traverse(c => {
154
+ if (c.dispose) c.dispose();
155
+ if (c.material) c.material.dispose();
122
156
  });
123
- }else{
157
+ } else {
124
158
  nextDownload.tile.setObject(instancedMesh);
125
159
  }
126
160
  });
127
-
128
- }else if(nextDownload.path.includes(".json")){
161
+
162
+ } else if (nextDownload.path.includes(".json")) {
129
163
  concurentDownloads++;
130
- fetch(nextDownload.path, {signal: nextDownload.abortController.signal}).then(result => {
164
+ fetch(nextDownload.path, { signal: nextDownload.abortController.signal }).then(result => {
131
165
  concurentDownloads--;
132
166
  if (!result.ok) {
133
167
  console.error("could not load tile with path : " + path)
134
168
  throw new Error(`couldn't load "${path}". Request failed with status ${result.status} : ${result.statusText}`);
135
169
  }
136
170
  return result.json();
137
-
171
+
138
172
  }).then(json => {
139
173
  nextDownload.tile.setObject(json, nextDownload.path);
140
174
  self.ready.unshift(nextDownload);
141
175
  })
142
- .catch(e=>console.error(e))
176
+ .catch(e => console.error(e))
143
177
  }
144
178
  }
145
179
  }
@@ -153,8 +187,8 @@ class InstancedTileLoader {
153
187
  }
154
188
  const download = this.nextReady.shift();
155
189
  if (!download) return 0;
156
-
157
- if(!!download.tile.addToScene)download.tile.addToScene();
190
+
191
+ if (!!download.tile.addToScene) download.tile.addToScene();
158
192
  return 1;
159
193
  }
160
194
 
@@ -162,7 +196,7 @@ class InstancedTileLoader {
162
196
  let smallestDistance = Number.MAX_VALUE;
163
197
  let closest = -1;
164
198
  for (let i = this.ready.length - 1; i >= 0; i--) {
165
-
199
+
166
200
  if (!this.ready[i].distanceFunction) {// if no distance function, must be a json, give absolute priority!
167
201
  this.nextReady.push(this.ready.splice(i, 1)[0]);
168
202
  }
@@ -205,7 +239,7 @@ class InstancedTileLoader {
205
239
  if (path.includes(".b3dm") || path.includes(".glb") || path.includes(".gltf")) {
206
240
  const tile = new MeshTile(self.scene);
207
241
  tile.addInstance(instancedOGC3DTile);
208
-
242
+
209
243
  self.cache.put(key, tile);
210
244
 
211
245
  const realAbortController = new AbortController();
@@ -229,7 +263,7 @@ class InstancedTileLoader {
229
263
  return true;
230
264
  },
231
265
  })
232
- }else if(path.includes(".json")){
266
+ } else if (path.includes(".json")) {
233
267
  const tile = new JsonTile();
234
268
  tile.addInstance(instancedOGC3DTile);
235
269
  self.cache.put(key, tile);
@@ -258,7 +292,7 @@ class InstancedTileLoader {
258
292
  }
259
293
 
260
294
 
261
-
295
+
262
296
  getNextDownloads() {
263
297
  let smallestDistance = Number.MAX_VALUE;
264
298
  let closest = -1;
@@ -267,7 +301,7 @@ class InstancedTileLoader {
267
301
  if (!download.shouldDoDownload()) {
268
302
  this.downloads.splice(i, 1);
269
303
  continue;
270
- }
304
+ }
271
305
  if (!download.distanceFunction) { // if no distance function, must be a json, give absolute priority!
272
306
  this.nextDownloads.push(this.downloads.splice(i, 1)[0]);
273
307
  }
@@ -275,7 +309,7 @@ class InstancedTileLoader {
275
309
  if (this.nextDownloads.length > 0) return;
276
310
  for (let i = this.downloads.length - 1; i >= 0; i--) {
277
311
  const download = this.downloads[i];
278
- const dist = download.distanceFunction()*download.level;
312
+ const dist = download.distanceFunction() * download.level;
279
313
  if (dist < smallestDistance) {
280
314
  smallestDistance = dist;
281
315
  closest = i;
@@ -301,12 +335,12 @@ class InstancedTileLoader {
301
335
  while (self.cache.size() > self.maxCachedItems && i < self.cache.size()) {
302
336
  i++;
303
337
  const entry = self.cache.head();
304
- if(entry.value.getCount()>0){
338
+ if (entry.value.getCount() > 0) {
305
339
  self.cache.remove(entry.key);
306
340
  self.cache.put(entry.key, entry.value);
307
- }else{
341
+ } else {
308
342
  self.cache.remove(entry.key);
309
- if(entry.value.instancedMesh){
343
+ if (entry.value.instancedMesh) {
310
344
  entry.value.instancedMesh.traverse((o) => {
311
345
  if (o.material) {
312
346
  // dispose materials