@stowkit/three-loader 0.1.26 → 0.1.28
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.
|
@@ -341,6 +341,7 @@ class MeshParser {
|
|
|
341
341
|
*/
|
|
342
342
|
class StowKitPack {
|
|
343
343
|
constructor(reader, ktx2Loader, dracoLoader) {
|
|
344
|
+
this.textureCache = new Map();
|
|
344
345
|
this.reader = reader;
|
|
345
346
|
this.ktx2Loader = ktx2Loader;
|
|
346
347
|
this.dracoLoader = dracoLoader;
|
|
@@ -695,8 +696,8 @@ class StowKitPack {
|
|
|
695
696
|
reader.PerfLogger.log(`[Perf] Parse mesh metadata: ${(performance.now() - parseStart).toFixed(2)}ms`);
|
|
696
697
|
// Load textures for materials
|
|
697
698
|
const textureStart = performance.now();
|
|
698
|
-
await this.loadMaterialTextures(parsedData.materialData, parsedData.materials);
|
|
699
|
-
reader.PerfLogger.log(`[Perf] Load textures: ${(performance.now() - textureStart).toFixed(2)}ms`);
|
|
699
|
+
const textureNames = await this.loadMaterialTextures(parsedData.materialData, parsedData.materials);
|
|
700
|
+
reader.PerfLogger.log(`[Perf] Load textures: ${(performance.now() - textureStart).toFixed(2)}ms (${textureNames.length > 0 ? textureNames.join(', ') : 'none'})`);
|
|
700
701
|
// Build Three.js scene with Draco decoder
|
|
701
702
|
const buildStart = performance.now();
|
|
702
703
|
const scene = await MeshParser.buildScene(parsedData, data, this.dracoLoader);
|
|
@@ -708,18 +709,28 @@ class StowKitPack {
|
|
|
708
709
|
* Load a texture by its canonical path/name
|
|
709
710
|
*/
|
|
710
711
|
async loadTexture(assetPath) {
|
|
711
|
-
//
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
712
|
+
// Check cache first
|
|
713
|
+
if (this.textureCache.has(assetPath)) {
|
|
714
|
+
reader.PerfLogger.log(`[Perf] Texture cache hit: ${assetPath}`);
|
|
715
|
+
return this.textureCache.get(assetPath);
|
|
715
716
|
}
|
|
716
|
-
//
|
|
717
|
-
const
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
717
|
+
// Cache the promise to avoid duplicate loads
|
|
718
|
+
const loadPromise = (async () => {
|
|
719
|
+
// Find asset by path
|
|
720
|
+
const assetIndex = this.reader.findAssetByPath(assetPath);
|
|
721
|
+
if (assetIndex < 0) {
|
|
722
|
+
throw new Error(`Texture not found: ${assetPath}`);
|
|
723
|
+
}
|
|
724
|
+
// Read texture data
|
|
725
|
+
const data = this.reader.readAssetData(assetIndex);
|
|
726
|
+
if (!data) {
|
|
727
|
+
throw new Error(`Failed to read texture data: ${assetPath}`);
|
|
728
|
+
}
|
|
729
|
+
// Load as KTX2
|
|
730
|
+
return await this.loadKTX2Texture(data);
|
|
731
|
+
})();
|
|
732
|
+
this.textureCache.set(assetPath, loadPromise);
|
|
733
|
+
return loadPromise;
|
|
723
734
|
}
|
|
724
735
|
/**
|
|
725
736
|
* Load audio by its canonical path/name
|
|
@@ -998,27 +1009,44 @@ class StowKitPack {
|
|
|
998
1009
|
* Close the pack and free resources
|
|
999
1010
|
*/
|
|
1000
1011
|
dispose() {
|
|
1012
|
+
this.textureCache.clear();
|
|
1001
1013
|
this.reader.close();
|
|
1002
1014
|
}
|
|
1003
1015
|
// Private methods moved from StowKitLoader
|
|
1004
1016
|
async loadMaterialTextures(materialData, materials) {
|
|
1017
|
+
// Collect all texture load promises to load in parallel
|
|
1018
|
+
const textureLoads = [];
|
|
1019
|
+
const uniqueTextures = new Set();
|
|
1005
1020
|
for (let i = 0; i < materialData.length; i++) {
|
|
1006
1021
|
const matData = materialData[i];
|
|
1007
|
-
const material = materials[i];
|
|
1008
1022
|
for (const prop of matData.properties) {
|
|
1009
|
-
// Trim and check for truly non-empty texture ID
|
|
1010
1023
|
const textureId = prop.textureId?.trim();
|
|
1011
1024
|
if (textureId && textureId.length > 0) {
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1025
|
+
uniqueTextures.add(textureId);
|
|
1026
|
+
textureLoads.push({
|
|
1027
|
+
materialIndex: i,
|
|
1028
|
+
propertyName: prop.fieldName,
|
|
1029
|
+
textureId: textureId,
|
|
1030
|
+
texturePromise: this.loadTexture(textureId).catch(error => {
|
|
1031
|
+
console.error(`Failed to load texture "${textureId}":`, error);
|
|
1032
|
+
throw error;
|
|
1033
|
+
})
|
|
1034
|
+
});
|
|
1019
1035
|
}
|
|
1020
1036
|
}
|
|
1021
1037
|
}
|
|
1038
|
+
// Load all textures in parallel
|
|
1039
|
+
const results = await Promise.allSettled(textureLoads.map(load => load.texturePromise));
|
|
1040
|
+
// Apply successfully loaded textures
|
|
1041
|
+
for (let i = 0; i < textureLoads.length; i++) {
|
|
1042
|
+
const result = results[i];
|
|
1043
|
+
if (result.status === 'fulfilled') {
|
|
1044
|
+
const load = textureLoads[i];
|
|
1045
|
+
const material = materials[load.materialIndex];
|
|
1046
|
+
this.applyTextureToMaterial(material, load.propertyName, result.value);
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
return Array.from(uniqueTextures);
|
|
1022
1050
|
}
|
|
1023
1051
|
async loadKTX2Texture(data) {
|
|
1024
1052
|
performance.now();
|