@stowkit/three-loader 0.1.30 → 0.1.32
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/dist/AssetCache.d.ts +54 -0
- package/dist/AssetCache.d.ts.map +1 -0
- package/dist/MeshParser.d.ts +2 -2
- package/dist/MeshParser.d.ts.map +1 -1
- package/dist/StowKitLoader.d.ts +4 -1
- package/dist/StowKitLoader.d.ts.map +1 -1
- package/dist/StowKitPack.d.ts +3 -1
- package/dist/StowKitPack.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/stowkit-three-loader.esm.js +235 -22
- package/dist/stowkit-three-loader.esm.js.map +1 -1
- package/dist/stowkit-three-loader.js +235 -21
- package/dist/stowkit-three-loader.js.map +1 -1
- package/package.json +1 -1
|
@@ -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"}
|
package/dist/MeshParser.d.ts
CHANGED
|
@@ -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
|
*/
|
package/dist/MeshParser.d.ts.map
CHANGED
|
@@ -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;
|
|
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;IAsE1K;;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;IA+FjM;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU;CAK5B"}
|
package/dist/StowKitLoader.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/StowKitPack.d.ts
CHANGED
|
@@ -10,7 +10,9 @@ export declare class StowKitPack {
|
|
|
10
10
|
private ktx2Loader;
|
|
11
11
|
private dracoLoader;
|
|
12
12
|
private textureCache;
|
|
13
|
-
|
|
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":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAC;AACxE,OAAO,EAAE,aAAa,EAAc,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"StowKitPack.d.ts","sourceRoot":"","sources":["../src/StowKitPack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAC;AACxE,OAAO,EAAE,aAAa,EAAc,MAAM,iBAAiB,CAAC;AAI5D;;GAEG;AACH,qBAAa,WAAW;IACb,MAAM,EAAE,aAAa,CAAC;IAC7B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,YAAY,CAA4D;IAChF,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,GAAE,MAAW,EAAE,WAAW,GAAE,MAAW;IAQnI;;OAEG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;IAe7D;;OAEG;YACW,gBAAgB;IAkY9B;;OAEG;IACG,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;IAoCvD;;OAEG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC;IA4BtE;;OAEG;IACG,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;IA0BvF;;OAEG;IACH,UAAU;IAIV;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG;IAIhC;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAI/C;;OAEG;IACH,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAKnD;;OAEG;IACG,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;IAUjE;;OAEG;IACG,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;IAY1D;;OAEG;IACG,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC;IAMzE;;OAEG;IACG,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAiBlE;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM;IAMlC;;OAEG;IACH,oBAAoB,CAAC,KAAK,EAAE,MAAM;IAIlC;;OAEG;IACH,kBAAkB,CAAC,KAAK,EAAE,MAAM;IAKhC;;OAEG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC;IAQvE;;OAEG;IACG,aAAa,CACf,gBAAgB,EAAE,KAAK,CAAC,KAAK,EAC7B,aAAa,EAAE,MAAM,GACtB,OAAO,CAAC;QAAE,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC;QAAC,MAAM,EAAE,KAAK,CAAC,eAAe,CAAC;QAAC,IAAI,EAAE,KAAK,CAAC,aAAa,CAAA;KAAE,CAAC;IAUrG;;OAEG;IACG,oBAAoB,CACtB,gBAAgB,EAAE,KAAK,CAAC,KAAK,EAC7B,cAAc,EAAE,MAAM,GACvB,OAAO,CAAC;QAAE,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC;QAAC,MAAM,EAAE,KAAK,CAAC,eAAe,CAAC;QAAC,IAAI,EAAE,KAAK,CAAC,aAAa,CAAA;KAAE,CAAC;IAUrG;;OAEG;IACG,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC;IAW3E;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA+H1B;;OAEG;IACH,OAAO,CAAC,cAAc;IAQtB;;OAEG;IACH,OAAO,IAAI,IAAI;YAMD,oBAAoB;YA0DpB,eAAe;IAqE7B,OAAO,CAAC,sBAAsB;IAwB9B,OAAO,CAAC,iBAAiB;CAM5B"}
|
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';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,23 @@ 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
|
+
const geometry = new THREE.BufferGeometry();
|
|
348
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(cached.positions, 3));
|
|
349
|
+
if (cached.normals) {
|
|
350
|
+
geometry.setAttribute('normal', new THREE.BufferAttribute(cached.normals, 3));
|
|
351
|
+
}
|
|
352
|
+
if (cached.uvs) {
|
|
353
|
+
geometry.setAttribute('uv', new THREE.BufferAttribute(cached.uvs, 2));
|
|
354
|
+
}
|
|
355
|
+
geometry.setIndex(new THREE.BufferAttribute(cached.indices, 1));
|
|
356
|
+
return geometry;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
195
359
|
// Extract the Draco compressed buffer
|
|
196
360
|
if (geoInfo.compressedBufferOffset + geoInfo.compressedBufferSize > dataBlob.length) {
|
|
197
361
|
throw new Error(`Compressed buffer out of bounds: offset=${geoInfo.compressedBufferOffset}, size=${geoInfo.compressedBufferSize}, dataLength=${dataBlob.length}`);
|
|
@@ -210,22 +374,35 @@ class MeshParser {
|
|
|
210
374
|
reject(new Error(`Failed to decode Draco geometry: ${error}`));
|
|
211
375
|
});
|
|
212
376
|
});
|
|
377
|
+
// Cache the decoded geometry
|
|
378
|
+
if (cacheKey && version) {
|
|
379
|
+
const posAttr = geometry.getAttribute('position');
|
|
380
|
+
const normAttr = geometry.getAttribute('normal');
|
|
381
|
+
const uvAttr = geometry.getAttribute('uv');
|
|
382
|
+
const indexAttr = geometry.index;
|
|
383
|
+
if (posAttr && 'array' in posAttr && indexAttr && 'array' in indexAttr) {
|
|
384
|
+
AssetMemoryCache.setGeometry(cacheKey, version, {
|
|
385
|
+
positions: posAttr.array,
|
|
386
|
+
normals: (normAttr && 'array' in normAttr) ? normAttr.array : undefined,
|
|
387
|
+
uvs: (uvAttr && 'array' in uvAttr) ? uvAttr.array : undefined,
|
|
388
|
+
indices: indexAttr.array
|
|
389
|
+
}).catch(() => {
|
|
390
|
+
// Silent fail - caching is optional
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
}
|
|
213
394
|
return geometry;
|
|
214
395
|
}
|
|
215
396
|
/**
|
|
216
397
|
* Build Three.js scene from parsed mesh data
|
|
217
398
|
*/
|
|
218
|
-
static async buildScene(parsedData, dataBlob, dracoLoader) {
|
|
399
|
+
static async buildScene(parsedData, dataBlob, dracoLoader, cacheKeyPrefix, version) {
|
|
219
400
|
const root = new THREE.Group();
|
|
220
401
|
root.name = 'StowKitMesh';
|
|
221
402
|
const { geometries, materials, nodes, meshIndices } = parsedData;
|
|
222
403
|
// Pre-load ALL geometries in parallel for maximum speed
|
|
223
|
-
const
|
|
224
|
-
const geometryPromises = geometries.map(geoInfo => this.createGeometry(geoInfo, dataBlob, dracoLoader));
|
|
404
|
+
const geometryPromises = geometries.map((geoInfo, index) => this.createGeometry(geoInfo, dataBlob, dracoLoader, cacheKeyPrefix ? `${cacheKeyPrefix}_geo${index}` : undefined, version));
|
|
225
405
|
const loadedGeometries = await Promise.all(geometryPromises);
|
|
226
|
-
const dracoTime = performance.now() - dracoStart;
|
|
227
|
-
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)`);
|
|
229
406
|
// Create all Three.js objects for nodes
|
|
230
407
|
const nodeObjects = [];
|
|
231
408
|
for (const node of nodes) {
|
|
@@ -312,11 +489,13 @@ class MeshParser {
|
|
|
312
489
|
* Represents an opened StowKit pack with methods to load assets by name
|
|
313
490
|
*/
|
|
314
491
|
class StowKitPack {
|
|
315
|
-
constructor(reader, ktx2Loader, dracoLoader) {
|
|
492
|
+
constructor(reader, ktx2Loader, dracoLoader, packUrl = '', packVersion = '') {
|
|
316
493
|
this.textureCache = new Map();
|
|
317
494
|
this.reader = reader;
|
|
318
495
|
this.ktx2Loader = ktx2Loader;
|
|
319
496
|
this.dracoLoader = dracoLoader;
|
|
497
|
+
this.packUrl = packUrl;
|
|
498
|
+
this.packVersion = packVersion || Date.now().toString();
|
|
320
499
|
}
|
|
321
500
|
/**
|
|
322
501
|
* Load a skinned mesh by its string ID
|
|
@@ -661,14 +840,10 @@ class StowKitPack {
|
|
|
661
840
|
// Parse mesh data
|
|
662
841
|
const parsedData = MeshParser.parseMeshData(metadata, data);
|
|
663
842
|
// Load textures for materials
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
const
|
|
667
|
-
|
|
668
|
-
PerfLogger.log(`[Perf] Textures: ${textureTime.toFixed(2)}ms (${textureNames.join(', ')})`);
|
|
669
|
-
}
|
|
670
|
-
// Build Three.js scene with Draco decoder
|
|
671
|
-
const scene = await MeshParser.buildScene(parsedData, data, this.dracoLoader);
|
|
843
|
+
await this.loadMaterialTextures(parsedData.materialData, parsedData.materials);
|
|
844
|
+
// Build Three.js scene with Draco decoder (with caching)
|
|
845
|
+
const cacheKey = `${this.packUrl}::${assetPath}`;
|
|
846
|
+
const scene = await MeshParser.buildScene(parsedData, data, this.dracoLoader, cacheKey, this.packVersion);
|
|
672
847
|
const totalTime = performance.now() - totalStart;
|
|
673
848
|
PerfLogger.log(`[Perf] === Mesh "${assetPath}": ${totalTime.toFixed(2)}ms total ===`);
|
|
674
849
|
return scene;
|
|
@@ -1016,12 +1191,24 @@ class StowKitPack {
|
|
|
1016
1191
|
return Array.from(uniqueTextures);
|
|
1017
1192
|
}
|
|
1018
1193
|
async loadKTX2Texture(data, textureName) {
|
|
1019
|
-
//
|
|
1194
|
+
// Try IndexedDB cache first
|
|
1195
|
+
const cacheKey = textureName ? `${this.packUrl}::${textureName}` : undefined;
|
|
1196
|
+
if (cacheKey) {
|
|
1197
|
+
const cached = await AssetMemoryCache.getTexture(cacheKey, this.packVersion);
|
|
1198
|
+
if (cached) {
|
|
1199
|
+
PerfLogger.log(`[Perf] ✓ Texture "${textureName}": 0ms (IndexedDB cache)`);
|
|
1200
|
+
const texture = new THREE.CompressedTexture([{ data: cached.data, width: cached.width, height: cached.height }], cached.width, cached.height, cached.format, THREE.UnsignedByteType);
|
|
1201
|
+
texture.needsUpdate = true;
|
|
1202
|
+
return texture;
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
// Decode using Basis transcoder
|
|
1206
|
+
const decodeStart = performance.now();
|
|
1020
1207
|
const arrayBuffer = data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
|
|
1021
1208
|
const blob = new Blob([arrayBuffer]);
|
|
1022
1209
|
const url = URL.createObjectURL(blob);
|
|
1023
1210
|
try {
|
|
1024
|
-
|
|
1211
|
+
const texture = await new Promise((resolve, reject) => {
|
|
1025
1212
|
this.ktx2Loader.load(url, (texture) => {
|
|
1026
1213
|
URL.revokeObjectURL(url);
|
|
1027
1214
|
texture.needsUpdate = true;
|
|
@@ -1031,6 +1218,24 @@ class StowKitPack {
|
|
|
1031
1218
|
reject(error);
|
|
1032
1219
|
});
|
|
1033
1220
|
});
|
|
1221
|
+
const decodeTime = performance.now() - decodeStart;
|
|
1222
|
+
PerfLogger.log(`[Perf] ✓ Texture "${textureName || 'unknown'}": ${decodeTime.toFixed(2)}ms (Basis decode ${texture.image?.width}x${texture.image?.height})`);
|
|
1223
|
+
// Cache the transcoded texture data to IndexedDB
|
|
1224
|
+
if (cacheKey && texture.mipmaps && texture.mipmaps.length > 0) {
|
|
1225
|
+
const mipmap = texture.mipmaps[0];
|
|
1226
|
+
const dataArray = new Uint8Array(mipmap.data.buffer, mipmap.data.byteOffset, mipmap.data.byteLength);
|
|
1227
|
+
AssetMemoryCache.setTexture(cacheKey, this.packVersion, {
|
|
1228
|
+
data: dataArray,
|
|
1229
|
+
width: mipmap.width,
|
|
1230
|
+
height: mipmap.height,
|
|
1231
|
+
format: texture.format,
|
|
1232
|
+
internalFormat: texture.format,
|
|
1233
|
+
compressed: true
|
|
1234
|
+
}).catch(() => {
|
|
1235
|
+
// Silent fail - caching is optional
|
|
1236
|
+
});
|
|
1237
|
+
}
|
|
1238
|
+
return texture;
|
|
1034
1239
|
}
|
|
1035
1240
|
catch (error) {
|
|
1036
1241
|
URL.revokeObjectURL(url);
|
|
@@ -1091,17 +1296,22 @@ class StowKitLoader {
|
|
|
1091
1296
|
throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
|
|
1092
1297
|
}
|
|
1093
1298
|
const arrayBuffer = await response.arrayBuffer();
|
|
1299
|
+
// Generate version for cache invalidation (based on file size)
|
|
1300
|
+
const version = `${arrayBuffer.byteLength}`;
|
|
1094
1301
|
// Create a new reader instance for this pack
|
|
1095
1302
|
const reader = new StowKitReader(this.wasmPath);
|
|
1096
1303
|
await reader.init();
|
|
1097
1304
|
await reader.open(arrayBuffer);
|
|
1098
1305
|
// Return pack wrapper with its own dedicated reader
|
|
1099
|
-
return new StowKitPack(reader, this.ktx2Loader, this.dracoLoader);
|
|
1306
|
+
return new StowKitPack(reader, this.ktx2Loader, this.dracoLoader, url, version);
|
|
1100
1307
|
}
|
|
1101
1308
|
/**
|
|
1102
1309
|
* Load a .stow pack from memory (ArrayBuffer, Blob, or File)
|
|
1310
|
+
* @param data - The .stow file data
|
|
1311
|
+
* @param options - Loader options
|
|
1312
|
+
* @param cacheKey - Optional unique identifier for caching (e.g., CDN URL). Recommended for files loaded from CDN.
|
|
1103
1313
|
*/
|
|
1104
|
-
static async loadFromMemory(data, options) {
|
|
1314
|
+
static async loadFromMemory(data, options, cacheKey) {
|
|
1105
1315
|
// Initialize loaders if needed
|
|
1106
1316
|
if (!this.initialized) {
|
|
1107
1317
|
await this.initialize(options);
|
|
@@ -1120,12 +1330,15 @@ class StowKitLoader {
|
|
|
1120
1330
|
else {
|
|
1121
1331
|
throw new Error('Data must be ArrayBuffer, Blob, or File');
|
|
1122
1332
|
}
|
|
1333
|
+
// Generate version for cache invalidation (based on file size)
|
|
1334
|
+
const version = `${arrayBuffer.byteLength}`;
|
|
1335
|
+
const packUrl = cacheKey || 'memory';
|
|
1123
1336
|
// Create a new reader instance for this pack
|
|
1124
1337
|
const reader = new StowKitReader(this.wasmPath);
|
|
1125
1338
|
await reader.init();
|
|
1126
1339
|
await reader.open(arrayBuffer);
|
|
1127
1340
|
// Return pack wrapper with its own dedicated reader
|
|
1128
|
-
return new StowKitPack(reader, this.ktx2Loader, this.dracoLoader);
|
|
1341
|
+
return new StowKitPack(reader, this.ktx2Loader, this.dracoLoader, packUrl, version);
|
|
1129
1342
|
}
|
|
1130
1343
|
/**
|
|
1131
1344
|
* Initialize the loader (called automatically on first load)
|
|
@@ -1152,5 +1365,5 @@ StowKitLoader.dracoLoader = null;
|
|
|
1152
1365
|
StowKitLoader.initialized = false;
|
|
1153
1366
|
StowKitLoader.wasmPath = '/stowkit/stowkit_reader.wasm';
|
|
1154
1367
|
|
|
1155
|
-
export { StowKitLoader, StowKitPack };
|
|
1368
|
+
export { AssetMemoryCache, StowKitLoader, StowKitPack };
|
|
1156
1369
|
//# sourceMappingURL=stowkit-three-loader.esm.js.map
|