@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.
@@ -9,6 +9,7 @@ export declare class StowKitPack {
9
9
  reader: StowKitReader;
10
10
  private ktx2Loader;
11
11
  private dracoLoader;
12
+ private textureCache;
12
13
  constructor(reader: StowKitReader, ktx2Loader: KTX2Loader, dracoLoader: DRACOLoader);
13
14
  /**
14
15
  * Load a skinned mesh by its string ID
@@ -1 +1 @@
1
- {"version":3,"file":"StowKitPack.d.ts","sourceRoot":"","sources":["../src/StowKitPack.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"StowKitPack.d.ts","sourceRoot":"","sources":["../src/StowKitPack.ts"],"names":[],"mappings":"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"}
@@ -321,6 +321,7 @@ class MeshParser {
321
321
  */
322
322
  class StowKitPack {
323
323
  constructor(reader, ktx2Loader, dracoLoader) {
324
+ this.textureCache = new Map();
324
325
  this.reader = reader;
325
326
  this.ktx2Loader = ktx2Loader;
326
327
  this.dracoLoader = dracoLoader;
@@ -675,8 +676,8 @@ class StowKitPack {
675
676
  PerfLogger.log(`[Perf] Parse mesh metadata: ${(performance.now() - parseStart).toFixed(2)}ms`);
676
677
  // Load textures for materials
677
678
  const textureStart = performance.now();
678
- await this.loadMaterialTextures(parsedData.materialData, parsedData.materials);
679
- PerfLogger.log(`[Perf] Load textures: ${(performance.now() - textureStart).toFixed(2)}ms`);
679
+ const textureNames = await this.loadMaterialTextures(parsedData.materialData, parsedData.materials);
680
+ PerfLogger.log(`[Perf] Load textures: ${(performance.now() - textureStart).toFixed(2)}ms (${textureNames.length > 0 ? textureNames.join(', ') : 'none'})`);
680
681
  // Build Three.js scene with Draco decoder
681
682
  const buildStart = performance.now();
682
683
  const scene = await MeshParser.buildScene(parsedData, data, this.dracoLoader);
@@ -688,18 +689,28 @@ class StowKitPack {
688
689
  * Load a texture by its canonical path/name
689
690
  */
690
691
  async loadTexture(assetPath) {
691
- // Find asset by path
692
- const assetIndex = this.reader.findAssetByPath(assetPath);
693
- if (assetIndex < 0) {
694
- throw new Error(`Texture not found: ${assetPath}`);
692
+ // Check cache first
693
+ if (this.textureCache.has(assetPath)) {
694
+ PerfLogger.log(`[Perf] Texture cache hit: ${assetPath}`);
695
+ return this.textureCache.get(assetPath);
695
696
  }
696
- // Read texture data
697
- const data = this.reader.readAssetData(assetIndex);
698
- if (!data) {
699
- throw new Error(`Failed to read texture data: ${assetPath}`);
700
- }
701
- // Load as KTX2
702
- return await this.loadKTX2Texture(data);
697
+ // Cache the promise to avoid duplicate loads
698
+ const loadPromise = (async () => {
699
+ // Find asset by path
700
+ const assetIndex = this.reader.findAssetByPath(assetPath);
701
+ if (assetIndex < 0) {
702
+ throw new Error(`Texture not found: ${assetPath}`);
703
+ }
704
+ // Read texture data
705
+ const data = this.reader.readAssetData(assetIndex);
706
+ if (!data) {
707
+ throw new Error(`Failed to read texture data: ${assetPath}`);
708
+ }
709
+ // Load as KTX2
710
+ return await this.loadKTX2Texture(data);
711
+ })();
712
+ this.textureCache.set(assetPath, loadPromise);
713
+ return loadPromise;
703
714
  }
704
715
  /**
705
716
  * Load audio by its canonical path/name
@@ -978,27 +989,44 @@ class StowKitPack {
978
989
  * Close the pack and free resources
979
990
  */
980
991
  dispose() {
992
+ this.textureCache.clear();
981
993
  this.reader.close();
982
994
  }
983
995
  // Private methods moved from StowKitLoader
984
996
  async loadMaterialTextures(materialData, materials) {
997
+ // Collect all texture load promises to load in parallel
998
+ const textureLoads = [];
999
+ const uniqueTextures = new Set();
985
1000
  for (let i = 0; i < materialData.length; i++) {
986
1001
  const matData = materialData[i];
987
- const material = materials[i];
988
1002
  for (const prop of matData.properties) {
989
- // Trim and check for truly non-empty texture ID
990
1003
  const textureId = prop.textureId?.trim();
991
1004
  if (textureId && textureId.length > 0) {
992
- try {
993
- const texture = await this.loadTexture(textureId);
994
- this.applyTextureToMaterial(material, prop.fieldName, texture);
995
- }
996
- catch (error) {
997
- console.error(`Failed to load texture "${textureId}":`, error);
998
- }
1005
+ uniqueTextures.add(textureId);
1006
+ textureLoads.push({
1007
+ materialIndex: i,
1008
+ propertyName: prop.fieldName,
1009
+ textureId: textureId,
1010
+ texturePromise: this.loadTexture(textureId).catch(error => {
1011
+ console.error(`Failed to load texture "${textureId}":`, error);
1012
+ throw error;
1013
+ })
1014
+ });
999
1015
  }
1000
1016
  }
1001
1017
  }
1018
+ // Load all textures in parallel
1019
+ const results = await Promise.allSettled(textureLoads.map(load => load.texturePromise));
1020
+ // Apply successfully loaded textures
1021
+ for (let i = 0; i < textureLoads.length; i++) {
1022
+ const result = results[i];
1023
+ if (result.status === 'fulfilled') {
1024
+ const load = textureLoads[i];
1025
+ const material = materials[load.materialIndex];
1026
+ this.applyTextureToMaterial(material, load.propertyName, result.value);
1027
+ }
1028
+ }
1029
+ return Array.from(uniqueTextures);
1002
1030
  }
1003
1031
  async loadKTX2Texture(data) {
1004
1032
  performance.now();