@needle-tools/gltf-progressive 3.6.0-alpha.2 → 3.6.0-alpha.3
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/CHANGELOG.md +3 -0
- package/gltf-progressive.js +517 -480
- package/gltf-progressive.min.js +9 -9
- package/gltf-progressive.umd.cjs +9 -9
- package/lib/extension.d.ts +6 -0
- package/lib/extension.js +80 -9
- package/lib/version.js +1 -1
- package/package.json +1 -1
package/lib/extension.js
CHANGED
|
@@ -223,13 +223,19 @@ export class NEEDLE_progressive {
|
|
|
223
223
|
}
|
|
224
224
|
// const info = this.onProgressiveLoadStart(context, source, mesh, null);
|
|
225
225
|
mesh["LOD:requested level"] = level;
|
|
226
|
-
|
|
226
|
+
const shouldLoad = () => mesh["LOD:requested level"] === level || this.shouldApplyStaleMeshLOD(mesh, level);
|
|
227
|
+
return NEEDLE_progressive.getOrLoadLOD(currentGeometry, level, {
|
|
228
|
+
isCurrent: shouldLoad,
|
|
229
|
+
}).then(geo => {
|
|
227
230
|
if (Array.isArray(geo)) {
|
|
228
231
|
const index = lodinfo.index || 0;
|
|
229
232
|
geo = geo[index];
|
|
230
233
|
}
|
|
231
|
-
|
|
232
|
-
|
|
234
|
+
const isLatestRequest = mesh["LOD:requested level"] === level;
|
|
235
|
+
if (isLatestRequest || this.shouldApplyStaleMeshLOD(mesh, level)) {
|
|
236
|
+
if (isLatestRequest) {
|
|
237
|
+
delete mesh["LOD:requested level"];
|
|
238
|
+
}
|
|
233
239
|
if (geo && currentGeometry != geo) {
|
|
234
240
|
const isGeometry = geo?.isBufferGeometry;
|
|
235
241
|
// if (debug == "verbose") console.log("Progressive Mesh " + mesh.name + " loaded", currentGeometry, "→", geo, "\n", mesh)
|
|
@@ -373,7 +379,14 @@ export class NEEDLE_progressive {
|
|
|
373
379
|
return pending.promise;
|
|
374
380
|
}
|
|
375
381
|
}
|
|
376
|
-
const
|
|
382
|
+
const requestId = material && slot ? this.nextTextureSlotRequestId(material, slot, level, force) : 0;
|
|
383
|
+
const isCurrentRequest = () => !material || !slot || this.getLatestTextureSlotRequest(material, slot)?.id === requestId;
|
|
384
|
+
const shouldLoad = () => isCurrentRequest() || this.shouldApplyStaleTextureSlotLOD(material, slot, level, force);
|
|
385
|
+
const promise = NEEDLE_progressive.getOrLoadLOD(current, level, {
|
|
386
|
+
isCurrent: shouldLoad,
|
|
387
|
+
}).then(tex => {
|
|
388
|
+
if (!isCurrentRequest() && !this.shouldApplyStaleTextureSlotLOD(material, slot, level, force))
|
|
389
|
+
return null;
|
|
377
390
|
// this can currently not happen
|
|
378
391
|
if (Array.isArray(tex)) {
|
|
379
392
|
console.warn("Progressive: Got an array of textures for a texture slot, this should not happen...");
|
|
@@ -415,7 +428,7 @@ export class NEEDLE_progressive {
|
|
|
415
428
|
return null;
|
|
416
429
|
});
|
|
417
430
|
if (material && slot) {
|
|
418
|
-
this.setPendingTextureSlotRequest(material, slot, level, force, promise);
|
|
431
|
+
this.setPendingTextureSlotRequest(material, slot, level, force, requestId, promise);
|
|
419
432
|
}
|
|
420
433
|
return promise;
|
|
421
434
|
}
|
|
@@ -423,6 +436,8 @@ export class NEEDLE_progressive {
|
|
|
423
436
|
// referenced by many slots and should only be disposed after every slot moved away.
|
|
424
437
|
static trackedTextureSlots = new WeakMap();
|
|
425
438
|
static pendingTextureSlotRequests = new WeakMap();
|
|
439
|
+
static latestTextureSlotRequests = new WeakMap();
|
|
440
|
+
static textureSlotRequestId = 0;
|
|
426
441
|
static trackCurrentMaterialTextureSlots(material) {
|
|
427
442
|
if (material.uniforms && (material.isRawShaderMaterial || material.isShaderMaterial === true)) {
|
|
428
443
|
const shaderMaterial = material;
|
|
@@ -444,17 +459,52 @@ export class NEEDLE_progressive {
|
|
|
444
459
|
static getPendingTextureSlotRequest(material, slot) {
|
|
445
460
|
return this.pendingTextureSlotRequests.get(material)?.get(slot);
|
|
446
461
|
}
|
|
447
|
-
static
|
|
462
|
+
static nextTextureSlotRequestId(material, slot, level, force) {
|
|
463
|
+
let slots = this.latestTextureSlotRequests.get(material);
|
|
464
|
+
if (!slots) {
|
|
465
|
+
slots = new Map();
|
|
466
|
+
this.latestTextureSlotRequests.set(material, slots);
|
|
467
|
+
}
|
|
468
|
+
const id = ++this.textureSlotRequestId;
|
|
469
|
+
slots.set(slot, { id, level, force });
|
|
470
|
+
return id;
|
|
471
|
+
}
|
|
472
|
+
static getLatestTextureSlotRequest(material, slot) {
|
|
473
|
+
return this.latestTextureSlotRequests.get(material)?.get(slot);
|
|
474
|
+
}
|
|
475
|
+
static shouldApplyStaleTextureSlotLOD(material, slot, level, force) {
|
|
476
|
+
if (!material || !slot)
|
|
477
|
+
return false;
|
|
478
|
+
const latest = this.getLatestTextureSlotRequest(material, slot);
|
|
479
|
+
const assigned = this.getMaterialTextureSlot(material, slot);
|
|
480
|
+
const assignedLODLevel = this.getAssignedLODInformation(assigned)?.level ?? Infinity;
|
|
481
|
+
if (level >= assignedLODLevel)
|
|
482
|
+
return false;
|
|
483
|
+
if (force) {
|
|
484
|
+
if (!latest)
|
|
485
|
+
return false;
|
|
486
|
+
return level >= latest.level;
|
|
487
|
+
}
|
|
488
|
+
return true;
|
|
489
|
+
}
|
|
490
|
+
static shouldApplyStaleMeshLOD(mesh, level) {
|
|
491
|
+
const latestLevel = mesh["LOD:requested level"];
|
|
492
|
+
if (typeof latestLevel !== "number")
|
|
493
|
+
return false;
|
|
494
|
+
const assignedLODLevel = this.getAssignedLODInformation(mesh.geometry)?.level ?? Infinity;
|
|
495
|
+
return level < assignedLODLevel && level >= latestLevel;
|
|
496
|
+
}
|
|
497
|
+
static setPendingTextureSlotRequest(material, slot, level, force, id, promise) {
|
|
448
498
|
let slots = this.pendingTextureSlotRequests.get(material);
|
|
449
499
|
if (!slots) {
|
|
450
500
|
slots = new Map();
|
|
451
501
|
this.pendingTextureSlotRequests.set(material, slots);
|
|
452
502
|
}
|
|
453
|
-
const request = { level, force, promise };
|
|
503
|
+
const request = { level, force, id, promise };
|
|
454
504
|
slots.set(slot, request);
|
|
455
505
|
promise.finally(() => {
|
|
456
506
|
const current = slots.get(slot);
|
|
457
|
-
if (current ===
|
|
507
|
+
if (current?.id === id) {
|
|
458
508
|
slots.delete(slot);
|
|
459
509
|
}
|
|
460
510
|
});
|
|
@@ -771,6 +821,8 @@ export class NEEDLE_progressive {
|
|
|
771
821
|
this.textureRefCounts.clear();
|
|
772
822
|
this.trackedTextureSlots = new WeakMap();
|
|
773
823
|
this.pendingTextureSlotRequests = new WeakMap();
|
|
824
|
+
this.latestTextureSlotRequests = new WeakMap();
|
|
825
|
+
this.textureSlotRequestId = 0;
|
|
774
826
|
}
|
|
775
827
|
}
|
|
776
828
|
/** Dispose a single cache entry's three.js resource(s) to free GPU memory. */
|
|
@@ -889,7 +941,7 @@ export class NEEDLE_progressive {
|
|
|
889
941
|
}
|
|
890
942
|
static workers = [];
|
|
891
943
|
static _workersIndex = 0;
|
|
892
|
-
static async getOrLoadLOD(current, level) {
|
|
944
|
+
static async getOrLoadLOD(current, level, options) {
|
|
893
945
|
const debugverbose = debug == "verbose";
|
|
894
946
|
/** this key is used to lookup the LOD information */
|
|
895
947
|
const LOD = this.getAssignedLODInformation(current);
|
|
@@ -962,7 +1014,17 @@ export class NEEDLE_progressive {
|
|
|
962
1014
|
const cached = await this.tryResolveLODCacheEntry(this.cache.get(KEY), KEY, lod_url, current, level, debugverbose);
|
|
963
1015
|
if (cached.found)
|
|
964
1016
|
return cached.value;
|
|
1017
|
+
if (options?.isCurrent?.() === false) {
|
|
1018
|
+
if (debugverbose)
|
|
1019
|
+
console.log(`Skipping stale LOD ${level} request before queue: ${lod_url}`);
|
|
1020
|
+
return null;
|
|
1021
|
+
}
|
|
965
1022
|
const slot = await this.queue.slot(lod_url);
|
|
1023
|
+
if (options?.isCurrent?.() === false) {
|
|
1024
|
+
if (debugverbose)
|
|
1025
|
+
console.log(`Skipping stale LOD ${level} request after queue: ${lod_url}`);
|
|
1026
|
+
return null;
|
|
1027
|
+
}
|
|
966
1028
|
// Another request can fill the cache while this one waits for a queue slot.
|
|
967
1029
|
// Re-checking here avoids duplicate loads for heavily instanced assets.
|
|
968
1030
|
const cachedAfterQueue = await this.tryResolveLODCacheEntry(this.cache.get(KEY), KEY, lod_url, current, level, debugverbose);
|
|
@@ -1143,10 +1205,19 @@ export class NEEDLE_progressive {
|
|
|
1143
1205
|
}
|
|
1144
1206
|
else {
|
|
1145
1207
|
if (current instanceof Texture) {
|
|
1208
|
+
if (options?.isCurrent?.() === false) {
|
|
1209
|
+
if (debugverbose)
|
|
1210
|
+
console.log(`Skipping stale texture LOD ${level} request: ${lod_url}`);
|
|
1211
|
+
return null;
|
|
1212
|
+
}
|
|
1146
1213
|
if (debugverbose)
|
|
1147
1214
|
console.log("Load texture from uri: " + lod_url);
|
|
1148
1215
|
const loader = new TextureLoader();
|
|
1149
1216
|
const tex = await loader.loadAsync(lod_url);
|
|
1217
|
+
if (options?.isCurrent?.() === false) {
|
|
1218
|
+
tex?.dispose();
|
|
1219
|
+
return null;
|
|
1220
|
+
}
|
|
1150
1221
|
if (tex) {
|
|
1151
1222
|
tex.guid = lodInfo.guid;
|
|
1152
1223
|
tex.flipY = false;
|
package/lib/version.js
CHANGED
package/package.json
CHANGED