@stowkit/three-loader 0.1.30 → 0.1.31

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.
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Persistent asset cache using IndexedDB
3
+ * Caches decoded Draco geometries and transcoded Basis textures
4
+ * Invalidates when source .stow file changes
5
+ */
6
+ interface CachedGeometry {
7
+ positions: Float32Array;
8
+ normals?: Float32Array;
9
+ uvs?: Float32Array;
10
+ indices: Uint32Array;
11
+ version: string;
12
+ }
13
+ interface CachedTexture {
14
+ data: Uint8Array;
15
+ width: number;
16
+ height: number;
17
+ format: number;
18
+ internalFormat: number;
19
+ compressed: boolean;
20
+ version: string;
21
+ }
22
+ export declare class AssetMemoryCache {
23
+ private static db;
24
+ private static initPromise;
25
+ private static DB_NAME;
26
+ private static DB_VERSION;
27
+ private static GEOMETRY_STORE;
28
+ private static TEXTURE_STORE;
29
+ private static init;
30
+ static getGeometry(key: string, version: string): Promise<CachedGeometry | null>;
31
+ static setGeometry(key: string, version: string, geometry: {
32
+ positions: Float32Array;
33
+ normals?: Float32Array;
34
+ uvs?: Float32Array;
35
+ indices: Uint32Array;
36
+ }): Promise<void>;
37
+ static getTexture(key: string, version: string): Promise<CachedTexture | null>;
38
+ static setTexture(key: string, version: string, textureData: {
39
+ data: Uint8Array;
40
+ width: number;
41
+ height: number;
42
+ format: number;
43
+ internalFormat: number;
44
+ compressed: boolean;
45
+ }): Promise<void>;
46
+ static clear(): Promise<void>;
47
+ /**
48
+ * Generate a version hash for cache invalidation
49
+ * Based on file size only
50
+ */
51
+ static generateVersion(fileSize: number): string;
52
+ }
53
+ export {};
54
+ //# sourceMappingURL=AssetCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssetCache.d.ts","sourceRoot":"","sources":["../src/AssetCache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,UAAU,cAAc;IACpB,SAAS,EAAE,YAAY,CAAC;IACxB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,GAAG,CAAC,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,aAAa;IACnB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,gBAAgB;IACzB,OAAO,CAAC,MAAM,CAAC,EAAE,CAA4B;IAC7C,OAAO,CAAC,MAAM,CAAC,WAAW,CAA8B;IACxD,OAAO,CAAC,MAAM,CAAC,OAAO,CAAuB;IAC7C,OAAO,CAAC,MAAM,CAAC,UAAU,CAAK;IAC9B,OAAO,CAAC,MAAM,CAAC,cAAc,CAAgB;IAC7C,OAAO,CAAC,MAAM,CAAC,aAAa,CAAc;mBAErB,IAAI;WA6BZ,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;WA0BzE,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE;QAC7D,SAAS,EAAE,YAAY,CAAC;QACxB,OAAO,CAAC,EAAE,YAAY,CAAC;QACvB,GAAG,CAAC,EAAE,YAAY,CAAC;QACnB,OAAO,EAAE,WAAW,CAAC;KACxB,GAAG,OAAO,CAAC,IAAI,CAAC;WAmBJ,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;WA0BvE,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE;QAC/D,IAAI,EAAE,UAAU,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,EAAE,OAAO,CAAC;KACvB,GAAG,OAAO,CAAC,IAAI,CAAC;WAmBJ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBnC;;;OAGG;IACH,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;CAGnD"}
@@ -55,11 +55,11 @@ export declare class MeshParser {
55
55
  /**
56
56
  * Create Three.js BufferGeometry from Draco compressed mesh data
57
57
  */
58
- static createGeometry(geoInfo: MeshGeometryInfo, dataBlob: Uint8Array, dracoLoader: DRACOLoader): Promise<THREE.BufferGeometry>;
58
+ static createGeometry(geoInfo: MeshGeometryInfo, dataBlob: Uint8Array, dracoLoader: DRACOLoader, cacheKey?: string, version?: string): Promise<THREE.BufferGeometry>;
59
59
  /**
60
60
  * Build Three.js scene from parsed mesh data
61
61
  */
62
- static buildScene(parsedData: ReturnType<typeof MeshParser.parseMeshData>, dataBlob: Uint8Array, dracoLoader: DRACOLoader): Promise<THREE.Group>;
62
+ static buildScene(parsedData: ReturnType<typeof MeshParser.parseMeshData>, dataBlob: Uint8Array, dracoLoader: DRACOLoader, cacheKeyPrefix?: string, version?: string): Promise<THREE.Group>;
63
63
  /**
64
64
  * Read null-terminated string from buffer
65
65
  */
@@ -1 +1 @@
1
- {"version":3,"file":"MeshParser.d.ts","sourceRoot":"","sources":["../src/MeshParser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAC;AAGxE,MAAM,WAAW,gBAAgB;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB,EAAE,MAAM,CAAC;IAC/B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,IAAI;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,qBAAqB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,qBAAqB,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,YAAY;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,UAAU;IAEnB;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,YAAY;IAyBxD;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,GAAG;QAClE,QAAQ,EAAE,YAAY,CAAC;QACvB,UAAU,EAAE,gBAAgB,EAAE,CAAC;QAC/B,SAAS,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC5B,YAAY,EAAE,YAAY,EAAE,CAAC;QAC7B,KAAK,EAAE,IAAI,EAAE,CAAC;QACd,WAAW,EAAE,WAAW,CAAC;KAC5B;IAwLD;;OAEG;WACU,cAAc,CAAC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC;IAkCrI;;OAEG;WACU,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;IAkGtJ;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU;CAK5B"}
1
+ {"version":3,"file":"MeshParser.d.ts","sourceRoot":"","sources":["../src/MeshParser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAC;AAIxE,MAAM,WAAW,gBAAgB;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB,EAAE,MAAM,CAAC;IAC/B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,IAAI;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,qBAAqB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,qBAAqB,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,YAAY;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,UAAU;IAEnB;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,YAAY;IAyBxD;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,GAAG;QAClE,QAAQ,EAAE,YAAY,CAAC;QACvB,UAAU,EAAE,gBAAgB,EAAE,CAAC;QAC/B,SAAS,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC5B,YAAY,EAAE,YAAY,EAAE,CAAC;QAC7B,KAAK,EAAE,IAAI,EAAE,CAAC;QACd,WAAW,EAAE,WAAW,CAAC;KAC5B;IAwLD;;OAEG;WACU,cAAc,CAAC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC;IAuE1K;;OAEG;WACU,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;IAoGjM;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU;CAK5B"}
@@ -38,8 +38,11 @@ export declare class StowKitLoader {
38
38
  static load(url: string, options?: StowKitLoaderOptions): Promise<StowKitPack>;
39
39
  /**
40
40
  * Load a .stow pack from memory (ArrayBuffer, Blob, or File)
41
+ * @param data - The .stow file data
42
+ * @param options - Loader options
43
+ * @param cacheKey - Optional unique identifier for caching (e.g., CDN URL). Recommended for files loaded from CDN.
41
44
  */
42
- static loadFromMemory(data: ArrayBuffer | Blob | File, options?: StowKitLoaderOptions): Promise<StowKitPack>;
45
+ static loadFromMemory(data: ArrayBuffer | Blob | File, options?: StowKitLoaderOptions, cacheKey?: string): Promise<StowKitPack>;
43
46
  /**
44
47
  * Initialize the loader (called automatically on first load)
45
48
  */
@@ -1 +1 @@
1
- {"version":3,"file":"StowKitLoader.d.ts","sourceRoot":"","sources":["../src/StowKitLoader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,WAAW,oBAAoB;IACjC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAAC,UAAU,CAA2B;IACpD,OAAO,CAAC,MAAM,CAAC,WAAW,CAA4B;IACtD,OAAO,CAAC,MAAM,CAAC,WAAW,CAAS;IACnC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA0C;IAEjE;;OAEG;WACU,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,CAAC;IAuBpF;;OAEG;WACU,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,CAAC;IA2BlH;;OAEG;mBACkB,UAAU;CAoBlC"}
1
+ {"version":3,"file":"StowKitLoader.d.ts","sourceRoot":"","sources":["../src/StowKitLoader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,WAAW,oBAAoB;IACjC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAAC,UAAU,CAA2B;IACpD,OAAO,CAAC,MAAM,CAAC,WAAW,CAA4B;IACtD,OAAO,CAAC,MAAM,CAAC,WAAW,CAAS;IACnC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA0C;IAEjE;;OAEG;WACU,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,CAAC;IA0BpF;;;;;OAKG;WACU,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,oBAAoB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAgCrI;;OAEG;mBACkB,UAAU;CAoBlC"}
@@ -10,7 +10,9 @@ export declare class StowKitPack {
10
10
  private ktx2Loader;
11
11
  private dracoLoader;
12
12
  private textureCache;
13
- constructor(reader: StowKitReader, ktx2Loader: KTX2Loader, dracoLoader: DRACOLoader);
13
+ private packVersion;
14
+ private packUrl;
15
+ constructor(reader: StowKitReader, ktx2Loader: KTX2Loader, dracoLoader: DRACOLoader, packUrl?: string, packVersion?: string);
14
16
  /**
15
17
  * Load a skinned mesh by its string ID
16
18
  */
@@ -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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"}
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  */
5
5
  export { StowKitLoader } from './StowKitLoader';
6
6
  export { StowKitPack } from './StowKitPack';
7
+ export { AssetMemoryCache } from './AssetCache';
7
8
  export type { StowKitLoaderOptions } from './StowKitLoader';
8
9
  export type { MeshGeometryInfo, MaterialPropertyValue, MaterialData, Node, MeshMetadata } from './MeshParser';
9
10
  export { AssetType, PerfLogger } from '@stowkit/reader';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EACR,gBAAgB,EAChB,qBAAqB,EACrB,YAAY,EACZ,IAAI,EACJ,YAAY,EACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,YAAY,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EACR,gBAAgB,EAChB,qBAAqB,EACrB,YAAY,EACZ,IAAI,EACJ,YAAY,EACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
@@ -4,6 +4,154 @@ import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
4
4
  import { PerfLogger, StowKitReader } from '@stowkit/reader';
5
5
  export { AssetType, PerfLogger } from '@stowkit/reader';
6
6
 
7
+ /**
8
+ * Persistent asset cache using IndexedDB
9
+ * Caches decoded Draco geometries and transcoded Basis textures
10
+ * Invalidates when source .stow file changes
11
+ */
12
+ class AssetMemoryCache {
13
+ static async init() {
14
+ if (this.db)
15
+ return;
16
+ if (this.initPromise)
17
+ return this.initPromise;
18
+ this.initPromise = new Promise((resolve, reject) => {
19
+ const request = indexedDB.open(this.DB_NAME, this.DB_VERSION);
20
+ request.onerror = () => reject(request.error);
21
+ request.onsuccess = () => {
22
+ this.db = request.result;
23
+ resolve();
24
+ };
25
+ request.onupgradeneeded = (event) => {
26
+ const db = event.target.result;
27
+ if (!db.objectStoreNames.contains(this.GEOMETRY_STORE)) {
28
+ db.createObjectStore(this.GEOMETRY_STORE);
29
+ }
30
+ if (!db.objectStoreNames.contains(this.TEXTURE_STORE)) {
31
+ db.createObjectStore(this.TEXTURE_STORE);
32
+ }
33
+ };
34
+ });
35
+ return this.initPromise;
36
+ }
37
+ static async getGeometry(key, version) {
38
+ try {
39
+ await this.init();
40
+ if (!this.db)
41
+ return null;
42
+ return new Promise((resolve) => {
43
+ const transaction = this.db.transaction([this.GEOMETRY_STORE], 'readonly');
44
+ const store = transaction.objectStore(this.GEOMETRY_STORE);
45
+ const request = store.get(key);
46
+ request.onsuccess = () => {
47
+ const cached = request.result;
48
+ if (cached && cached.version === version) {
49
+ resolve(cached);
50
+ }
51
+ else {
52
+ resolve(null);
53
+ }
54
+ };
55
+ request.onerror = () => resolve(null);
56
+ });
57
+ }
58
+ catch {
59
+ return null;
60
+ }
61
+ }
62
+ static async setGeometry(key, version, geometry) {
63
+ try {
64
+ await this.init();
65
+ if (!this.db)
66
+ return;
67
+ const cached = { ...geometry, version };
68
+ return new Promise((resolve) => {
69
+ const transaction = this.db.transaction([this.GEOMETRY_STORE], 'readwrite');
70
+ const store = transaction.objectStore(this.GEOMETRY_STORE);
71
+ store.put(cached, key);
72
+ transaction.oncomplete = () => resolve();
73
+ transaction.onerror = () => resolve();
74
+ });
75
+ }
76
+ catch {
77
+ // Silently fail if IndexedDB unavailable
78
+ }
79
+ }
80
+ static async getTexture(key, version) {
81
+ try {
82
+ await this.init();
83
+ if (!this.db)
84
+ return null;
85
+ return new Promise((resolve) => {
86
+ const transaction = this.db.transaction([this.TEXTURE_STORE], 'readonly');
87
+ const store = transaction.objectStore(this.TEXTURE_STORE);
88
+ const request = store.get(key);
89
+ request.onsuccess = () => {
90
+ const cached = request.result;
91
+ if (cached && cached.version === version) {
92
+ resolve(cached);
93
+ }
94
+ else {
95
+ resolve(null);
96
+ }
97
+ };
98
+ request.onerror = () => resolve(null);
99
+ });
100
+ }
101
+ catch {
102
+ return null;
103
+ }
104
+ }
105
+ static async setTexture(key, version, textureData) {
106
+ try {
107
+ await this.init();
108
+ if (!this.db)
109
+ return;
110
+ const cached = { ...textureData, version };
111
+ return new Promise((resolve) => {
112
+ const transaction = this.db.transaction([this.TEXTURE_STORE], 'readwrite');
113
+ const store = transaction.objectStore(this.TEXTURE_STORE);
114
+ store.put(cached, key);
115
+ transaction.oncomplete = () => resolve();
116
+ transaction.onerror = () => resolve();
117
+ });
118
+ }
119
+ catch {
120
+ // Silently fail if IndexedDB unavailable
121
+ }
122
+ }
123
+ static async clear() {
124
+ try {
125
+ await this.init();
126
+ if (!this.db)
127
+ return;
128
+ return new Promise((resolve) => {
129
+ const transaction = this.db.transaction([this.GEOMETRY_STORE, this.TEXTURE_STORE], 'readwrite');
130
+ transaction.objectStore(this.GEOMETRY_STORE).clear();
131
+ transaction.objectStore(this.TEXTURE_STORE).clear();
132
+ transaction.oncomplete = () => resolve();
133
+ transaction.onerror = () => resolve();
134
+ });
135
+ }
136
+ catch {
137
+ // Silently fail
138
+ }
139
+ }
140
+ /**
141
+ * Generate a version hash for cache invalidation
142
+ * Based on file size only
143
+ */
144
+ static generateVersion(fileSize) {
145
+ return `${fileSize}`;
146
+ }
147
+ }
148
+ AssetMemoryCache.db = null;
149
+ AssetMemoryCache.initPromise = null;
150
+ AssetMemoryCache.DB_NAME = 'StowKitAssetCache';
151
+ AssetMemoryCache.DB_VERSION = 1;
152
+ AssetMemoryCache.GEOMETRY_STORE = 'geometries';
153
+ AssetMemoryCache.TEXTURE_STORE = 'textures';
154
+
7
155
  class MeshParser {
8
156
  /**
9
157
  * Parse mesh metadata from binary data
@@ -191,7 +339,24 @@ class MeshParser {
191
339
  /**
192
340
  * Create Three.js BufferGeometry from Draco compressed mesh data
193
341
  */
194
- static async createGeometry(geoInfo, dataBlob, dracoLoader) {
342
+ static async createGeometry(geoInfo, dataBlob, dracoLoader, cacheKey, version) {
343
+ // Try loading from IndexedDB cache first
344
+ if (cacheKey && version) {
345
+ const cached = await AssetMemoryCache.getGeometry(cacheKey, version);
346
+ if (cached) {
347
+ PerfLogger.log(`[Perf] Geometry cache hit: ${cacheKey}`);
348
+ const geometry = new THREE.BufferGeometry();
349
+ geometry.setAttribute('position', new THREE.BufferAttribute(cached.positions, 3));
350
+ if (cached.normals) {
351
+ geometry.setAttribute('normal', new THREE.BufferAttribute(cached.normals, 3));
352
+ }
353
+ if (cached.uvs) {
354
+ geometry.setAttribute('uv', new THREE.BufferAttribute(cached.uvs, 2));
355
+ }
356
+ geometry.setIndex(new THREE.BufferAttribute(cached.indices, 1));
357
+ return geometry;
358
+ }
359
+ }
195
360
  // Extract the Draco compressed buffer
196
361
  if (geoInfo.compressedBufferOffset + geoInfo.compressedBufferSize > dataBlob.length) {
197
362
  throw new Error(`Compressed buffer out of bounds: offset=${geoInfo.compressedBufferOffset}, size=${geoInfo.compressedBufferSize}, dataLength=${dataBlob.length}`);
@@ -210,22 +375,39 @@ class MeshParser {
210
375
  reject(new Error(`Failed to decode Draco geometry: ${error}`));
211
376
  });
212
377
  });
378
+ // Cache the decoded geometry
379
+ if (cacheKey && version) {
380
+ const posAttr = geometry.getAttribute('position');
381
+ const normAttr = geometry.getAttribute('normal');
382
+ const uvAttr = geometry.getAttribute('uv');
383
+ const indexAttr = geometry.index;
384
+ if (posAttr && 'array' in posAttr && indexAttr && 'array' in indexAttr) {
385
+ AssetMemoryCache.setGeometry(cacheKey, version, {
386
+ positions: posAttr.array,
387
+ normals: (normAttr && 'array' in normAttr) ? normAttr.array : undefined,
388
+ uvs: (uvAttr && 'array' in uvAttr) ? uvAttr.array : undefined,
389
+ indices: indexAttr.array
390
+ }).catch(() => {
391
+ // Silent fail - caching is optional
392
+ });
393
+ }
394
+ }
213
395
  return geometry;
214
396
  }
215
397
  /**
216
398
  * Build Three.js scene from parsed mesh data
217
399
  */
218
- static async buildScene(parsedData, dataBlob, dracoLoader) {
400
+ static async buildScene(parsedData, dataBlob, dracoLoader, cacheKeyPrefix, version) {
219
401
  const root = new THREE.Group();
220
402
  root.name = 'StowKitMesh';
221
403
  const { geometries, materials, nodes, meshIndices } = parsedData;
222
404
  // Pre-load ALL geometries in parallel for maximum speed
223
405
  const dracoStart = performance.now();
224
- const geometryPromises = geometries.map(geoInfo => this.createGeometry(geoInfo, dataBlob, dracoLoader));
406
+ const geometryPromises = geometries.map((geoInfo, index) => this.createGeometry(geoInfo, dataBlob, dracoLoader, cacheKeyPrefix ? `${cacheKeyPrefix}_geo${index}` : undefined, version));
225
407
  const loadedGeometries = await Promise.all(geometryPromises);
226
408
  const dracoTime = performance.now() - dracoStart;
227
409
  const totalVerts = geometries.reduce((sum, g) => sum + g.vertexCount, 0);
228
- PerfLogger.log(`[Perf] Draco decode: ${dracoTime.toFixed(2)}ms (${geometries.length} meshes, ${totalVerts} total vertices)`);
410
+ PerfLogger.log(`[Perf] Draco: ${dracoTime.toFixed(2)}ms (${geometries.length} meshes, ${totalVerts} verts)`);
229
411
  // Create all Three.js objects for nodes
230
412
  const nodeObjects = [];
231
413
  for (const node of nodes) {
@@ -312,11 +494,13 @@ class MeshParser {
312
494
  * Represents an opened StowKit pack with methods to load assets by name
313
495
  */
314
496
  class StowKitPack {
315
- constructor(reader, ktx2Loader, dracoLoader) {
497
+ constructor(reader, ktx2Loader, dracoLoader, packUrl = '', packVersion = '') {
316
498
  this.textureCache = new Map();
317
499
  this.reader = reader;
318
500
  this.ktx2Loader = ktx2Loader;
319
501
  this.dracoLoader = dracoLoader;
502
+ this.packUrl = packUrl;
503
+ this.packVersion = packVersion || Date.now().toString();
320
504
  }
321
505
  /**
322
506
  * Load a skinned mesh by its string ID
@@ -667,8 +851,9 @@ class StowKitPack {
667
851
  if (textureNames.length > 0) {
668
852
  PerfLogger.log(`[Perf] Textures: ${textureTime.toFixed(2)}ms (${textureNames.join(', ')})`);
669
853
  }
670
- // Build Three.js scene with Draco decoder
671
- const scene = await MeshParser.buildScene(parsedData, data, this.dracoLoader);
854
+ // Build Three.js scene with Draco decoder (with caching)
855
+ const cacheKey = `${this.packUrl}::${assetPath}`;
856
+ const scene = await MeshParser.buildScene(parsedData, data, this.dracoLoader, cacheKey, this.packVersion);
672
857
  const totalTime = performance.now() - totalStart;
673
858
  PerfLogger.log(`[Perf] === Mesh "${assetPath}": ${totalTime.toFixed(2)}ms total ===`);
674
859
  return scene;
@@ -1016,14 +1201,29 @@ class StowKitPack {
1016
1201
  return Array.from(uniqueTextures);
1017
1202
  }
1018
1203
  async loadKTX2Texture(data, textureName) {
1204
+ // Try IndexedDB cache first
1205
+ const cacheKey = textureName ? `${this.packUrl}::${textureName}` : undefined;
1206
+ if (cacheKey) {
1207
+ const startCache = performance.now();
1208
+ const cached = await AssetMemoryCache.getTexture(cacheKey, this.packVersion);
1209
+ if (cached) {
1210
+ PerfLogger.log(`[Perf] Texture cache hit (IndexedDB): ${textureName} (${(performance.now() - startCache).toFixed(2)}ms)`);
1211
+ const texture = new THREE.CompressedTexture([{ data: cached.data, width: cached.width, height: cached.height }], cached.width, cached.height, cached.format, THREE.UnsignedByteType);
1212
+ texture.needsUpdate = true;
1213
+ return texture;
1214
+ }
1215
+ }
1019
1216
  // Create blob URL - KTX2Loader requires a URL, can't use ArrayBuffer directly
1020
1217
  const arrayBuffer = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
1021
1218
  const blob = new Blob([arrayBuffer]);
1022
1219
  const url = URL.createObjectURL(blob);
1023
1220
  try {
1024
- return await new Promise((resolve, reject) => {
1221
+ const decodeStart = performance.now();
1222
+ const texture = await new Promise((resolve, reject) => {
1025
1223
  this.ktx2Loader.load(url, (texture) => {
1026
1224
  URL.revokeObjectURL(url);
1225
+ const decodeTime = performance.now() - decodeStart;
1226
+ PerfLogger.log(`[Perf] Basis decode: ${decodeTime.toFixed(2)}ms (${textureName || 'unknown'}, ${texture.image?.width}x${texture.image?.height})`);
1027
1227
  texture.needsUpdate = true;
1028
1228
  resolve(texture);
1029
1229
  }, undefined, (error) => {
@@ -1031,6 +1231,22 @@ class StowKitPack {
1031
1231
  reject(error);
1032
1232
  });
1033
1233
  });
1234
+ // Cache the transcoded texture data to IndexedDB
1235
+ if (cacheKey && texture.mipmaps && texture.mipmaps.length > 0) {
1236
+ const mipmap = texture.mipmaps[0];
1237
+ const dataArray = new Uint8Array(mipmap.data.buffer, mipmap.data.byteOffset, mipmap.data.byteLength);
1238
+ AssetMemoryCache.setTexture(cacheKey, this.packVersion, {
1239
+ data: dataArray,
1240
+ width: mipmap.width,
1241
+ height: mipmap.height,
1242
+ format: texture.format,
1243
+ internalFormat: texture.format,
1244
+ compressed: true
1245
+ }).catch(() => {
1246
+ // Silent fail - caching is optional
1247
+ });
1248
+ }
1249
+ return texture;
1034
1250
  }
1035
1251
  catch (error) {
1036
1252
  URL.revokeObjectURL(url);
@@ -1091,17 +1307,22 @@ class StowKitLoader {
1091
1307
  throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
1092
1308
  }
1093
1309
  const arrayBuffer = await response.arrayBuffer();
1310
+ // Generate version for cache invalidation (based on file size)
1311
+ const version = `${arrayBuffer.byteLength}`;
1094
1312
  // Create a new reader instance for this pack
1095
1313
  const reader = new StowKitReader(this.wasmPath);
1096
1314
  await reader.init();
1097
1315
  await reader.open(arrayBuffer);
1098
1316
  // Return pack wrapper with its own dedicated reader
1099
- return new StowKitPack(reader, this.ktx2Loader, this.dracoLoader);
1317
+ return new StowKitPack(reader, this.ktx2Loader, this.dracoLoader, url, version);
1100
1318
  }
1101
1319
  /**
1102
1320
  * Load a .stow pack from memory (ArrayBuffer, Blob, or File)
1321
+ * @param data - The .stow file data
1322
+ * @param options - Loader options
1323
+ * @param cacheKey - Optional unique identifier for caching (e.g., CDN URL). Recommended for files loaded from CDN.
1103
1324
  */
1104
- static async loadFromMemory(data, options) {
1325
+ static async loadFromMemory(data, options, cacheKey) {
1105
1326
  // Initialize loaders if needed
1106
1327
  if (!this.initialized) {
1107
1328
  await this.initialize(options);
@@ -1120,12 +1341,15 @@ class StowKitLoader {
1120
1341
  else {
1121
1342
  throw new Error('Data must be ArrayBuffer, Blob, or File');
1122
1343
  }
1344
+ // Generate version for cache invalidation (based on file size)
1345
+ const version = `${arrayBuffer.byteLength}`;
1346
+ const packUrl = cacheKey || 'memory';
1123
1347
  // Create a new reader instance for this pack
1124
1348
  const reader = new StowKitReader(this.wasmPath);
1125
1349
  await reader.init();
1126
1350
  await reader.open(arrayBuffer);
1127
1351
  // Return pack wrapper with its own dedicated reader
1128
- return new StowKitPack(reader, this.ktx2Loader, this.dracoLoader);
1352
+ return new StowKitPack(reader, this.ktx2Loader, this.dracoLoader, packUrl, version);
1129
1353
  }
1130
1354
  /**
1131
1355
  * Initialize the loader (called automatically on first load)
@@ -1152,5 +1376,5 @@ StowKitLoader.dracoLoader = null;
1152
1376
  StowKitLoader.initialized = false;
1153
1377
  StowKitLoader.wasmPath = '/stowkit/stowkit_reader.wasm';
1154
1378
 
1155
- export { StowKitLoader, StowKitPack };
1379
+ export { AssetMemoryCache, StowKitLoader, StowKitPack };
1156
1380
  //# sourceMappingURL=stowkit-three-loader.esm.js.map