@stowkit/three-loader 0.1.3 → 0.1.4

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/README.md CHANGED
@@ -17,6 +17,10 @@ import { StowKitLoader } from '@stowkit/three-loader';
17
17
  // Create loader (auto-configured with defaults)
18
18
  const loader = new StowKitLoader();
19
19
 
20
+ // Optional: Set custom decoder paths
21
+ // loader.setDracoDecoderPath('/custom-draco-path/');
22
+ // loader.setTranscoderPath('/custom-basis-path/');
23
+
20
24
  // Open a .stow pack file
21
25
  await loader.openPack('assets.stow');
22
26
 
@@ -485,14 +489,18 @@ Place these files in your public folder:
485
489
  ```
486
490
  public/
487
491
  ├── stowkit_reader.wasm # WASM reader module
488
- └── basis/ # Basis Universal transcoder
489
- ├── basis_transcoder.js
490
- └── basis_transcoder.wasm
492
+ ├── basis/ # Basis Universal transcoder (for textures)
493
+ ├── basis_transcoder.js
494
+ └── basis_transcoder.wasm
495
+ └── draco/ # Draco decoder (for meshes)
496
+ ├── draco_decoder.js
497
+ └── draco_decoder.wasm
491
498
  ```
492
499
 
493
500
  **Get the files:**
494
501
  - `stowkit_reader.wasm` - Included with `@stowkit/reader` package
495
502
  - Basis transcoder - From [three.js examples](https://github.com/mrdoob/three.js/tree/dev/examples/jsm/libs/basis)
503
+ - Draco decoder - From [three.js examples](https://github.com/mrdoob/three.js/tree/dev/examples/jsm/libs/draco)
496
504
 
497
505
  ### Three.js Version
498
506
 
@@ -1,16 +1,14 @@
1
1
  import * as THREE from 'three';
2
+ import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
2
3
  export interface MeshGeometryInfo {
3
4
  vertexCount: number;
4
5
  indexCount: number;
5
- vertexBufferOffset: number;
6
- indexBufferOffset: number;
7
- normalBufferOffset: number;
8
- uvBufferOffset: number;
9
- vertexBufferSize: number;
10
- indexBufferSize: number;
11
- normalBufferSize: number;
12
- uvBufferSize: number;
6
+ hasNormals: number;
7
+ hasUVs: number;
8
+ compressedBufferOffset: number;
9
+ compressedBufferSize: number;
13
10
  materialIndex: number;
11
+ padding: number;
14
12
  }
15
13
  export interface Node {
16
14
  name: string;
@@ -55,13 +53,13 @@ export declare class MeshParser {
55
53
  meshIndices: Uint32Array;
56
54
  };
57
55
  /**
58
- * Create Three.js BufferGeometry from mesh data
56
+ * Create Three.js BufferGeometry from Draco compressed mesh data
59
57
  */
60
- static createGeometry(geoInfo: MeshGeometryInfo, dataBlob: Uint8Array): THREE.BufferGeometry;
58
+ static createGeometry(geoInfo: MeshGeometryInfo, dataBlob: Uint8Array, dracoLoader: DRACOLoader): Promise<THREE.BufferGeometry>;
61
59
  /**
62
60
  * Build Three.js scene from parsed mesh data
63
61
  */
64
- static buildScene(parsedData: ReturnType<typeof MeshParser.parseMeshData>, dataBlob: Uint8Array): THREE.Group;
62
+ static buildScene(parsedData: ReturnType<typeof MeshParser.parseMeshData>, dataBlob: Uint8Array, dracoLoader: DRACOLoader): Promise<THREE.Group>;
65
63
  /**
66
64
  * Read null-terminated string from buffer
67
65
  */
@@ -1 +1 @@
1
- {"version":3,"file":"MeshParser.d.ts","sourceRoot":"","sources":["../src/MeshParser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,WAAW,gBAAgB;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACzB;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;IAcxD;;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;IAoMD;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,GAAG,KAAK,CAAC,cAAc;IAwF5F;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,UAAU,GAAG,KAAK,CAAC,KAAK;IAsI7G;;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;AAExE,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;IAcxD;;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;IAiMD;;OAEG;WACU,cAAc,CAAC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC;IA4DrI;;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;IAuItJ;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,UAAU;CAK5B"}
@@ -33,8 +33,13 @@ export interface StowKitLoaderParameters {
33
33
  export declare class StowKitLoader extends THREE.Loader {
34
34
  private reader;
35
35
  private ktx2Loader;
36
+ private dracoLoader;
36
37
  private ownedReader;
37
38
  constructor(manager?: THREE.LoadingManager, parameters?: StowKitLoaderParameters);
39
+ /**
40
+ * Set the path to the Draco decoder
41
+ */
42
+ setDracoDecoderPath(path: string): this;
38
43
  /**
39
44
  * Set the path to the Basis Universal transcoder
40
45
  */
@@ -48,6 +53,14 @@ export declare class StowKitLoader extends THREE.Loader {
48
53
  * @param url - URL to the .stow file
49
54
  */
50
55
  openPack(url: string): Promise<void>;
56
+ /**
57
+ * Load and parse a mesh asset by its index
58
+ * @param index - Asset index
59
+ * @param onLoad - Callback when loading completes
60
+ * @param onProgress - Progress callback
61
+ * @param onError - Error callback
62
+ */
63
+ loadMeshByIndex(index: number, onLoad?: (scene: THREE.Group) => void, onProgress?: (event: ProgressEvent) => void, onError?: (error: Error) => void): Promise<THREE.Group>;
51
64
  /**
52
65
  * Load and parse a mesh asset from a StowKit pack
53
66
  * @param url - URL to the .stow file (or omit if already opened with openPack)
@@ -1 +1 @@
1
- {"version":3,"file":"StowKitLoader.d.ts","sourceRoot":"","sources":["../src/StowKitLoader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"StowKitLoader.d.ts","sourceRoot":"","sources":["../src/StowKitLoader.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import * as THREE from 'three';
2
2
  import { KTX2Loader } from 'three/examples/jsm/loaders/KTX2Loader.js';
3
+ import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
3
4
  import { StowKitReader } from '@stowkit/reader';
4
5
 
5
6
  class MeshParser {
@@ -30,8 +31,8 @@ class MeshParser {
30
31
  console.log(`Mesh counts: ${metadata.meshGeometryCount} geometries, ${metadata.materialCount} materials, ${metadata.nodeCount} nodes`);
31
32
  // Check if the metadata blob contains just the header or all the mesh info
32
33
  const expectedMetadataSize = 140 +
33
- (metadata.meshGeometryCount * 76) +
34
- (metadata.materialCount * 64) +
34
+ (metadata.meshGeometryCount * 40) + // Draco compressed (40 bytes each)
35
+ (metadata.materialCount * 196) + // MaterialData header
35
36
  (metadata.nodeCount * 116);
36
37
  let hasExtendedMetadata = metadataBlob.length >= expectedMetadataSize;
37
38
  console.log(`Expected metadata size: ${expectedMetadataSize}, actual: ${metadataBlob.length}, has extended: ${hasExtendedMetadata}`);
@@ -39,28 +40,25 @@ class MeshParser {
39
40
  const sourceBlob = hasExtendedMetadata ? metadataBlob : dataBlob;
40
41
  const metaView = new DataView(sourceBlob.buffer, sourceBlob.byteOffset, sourceBlob.byteLength);
41
42
  let offset = hasExtendedMetadata ? 140 : 0; // Start after MeshMetadata if in metadata blob, or at beginning of data blob
42
- // Parse geometry infos
43
+ // Parse geometry infos (now Draco compressed!)
43
44
  const geometries = [];
44
45
  for (let i = 0; i < metadata.meshGeometryCount; i++) {
45
- if (offset + 76 > sourceBlob.length) {
46
+ if (offset + 40 > sourceBlob.length) {
46
47
  console.warn(`Data truncated at geometry ${i}/${metadata.meshGeometryCount}`);
47
48
  break;
48
49
  }
49
50
  const geo = {
50
51
  vertexCount: metaView.getUint32(offset, true),
51
52
  indexCount: metaView.getUint32(offset + 4, true),
52
- vertexBufferOffset: Number(metaView.getBigUint64(offset + 8, true)),
53
- indexBufferOffset: Number(metaView.getBigUint64(offset + 16, true)),
54
- normalBufferOffset: Number(metaView.getBigUint64(offset + 24, true)),
55
- uvBufferOffset: Number(metaView.getBigUint64(offset + 32, true)),
56
- vertexBufferSize: Number(metaView.getBigUint64(offset + 40, true)),
57
- indexBufferSize: Number(metaView.getBigUint64(offset + 48, true)),
58
- normalBufferSize: Number(metaView.getBigUint64(offset + 56, true)),
59
- uvBufferSize: Number(metaView.getBigUint64(offset + 64, true)),
60
- materialIndex: metaView.getUint32(offset + 72, true)
53
+ hasNormals: metaView.getUint32(offset + 8, true),
54
+ hasUVs: metaView.getUint32(offset + 12, true),
55
+ compressedBufferOffset: Number(metaView.getBigUint64(offset + 16, true)),
56
+ compressedBufferSize: Number(metaView.getBigUint64(offset + 24, true)),
57
+ materialIndex: metaView.getUint32(offset + 32, true),
58
+ padding: metaView.getUint32(offset + 36, true)
61
59
  };
62
60
  geometries.push(geo);
63
- offset += 76; // Size of MeshGeometryInfo
61
+ offset += 40; // Size of MeshGeometryInfo (Draco compressed)
64
62
  }
65
63
  // Parse materials - MaterialData structure: name[64] + schema_id[128] + property_count(4) = 196 bytes
66
64
  const materialData = [];
@@ -187,76 +185,40 @@ class MeshParser {
187
185
  return { metadata, geometries, materials, materialData, nodes, meshIndices };
188
186
  }
189
187
  /**
190
- * Create Three.js BufferGeometry from mesh data
188
+ * Create Three.js BufferGeometry from Draco compressed mesh data
191
189
  */
192
- static createGeometry(geoInfo, dataBlob) {
193
- console.log('Creating geometry:', {
190
+ static async createGeometry(geoInfo, dataBlob, dracoLoader) {
191
+ console.log('Decoding Draco geometry:', {
194
192
  vertexCount: geoInfo.vertexCount,
195
193
  indexCount: geoInfo.indexCount,
196
- vertexOffset: geoInfo.vertexBufferOffset,
197
- vertexSize: geoInfo.vertexBufferSize,
198
- dataBlobSize: dataBlob.length
194
+ hasNormals: geoInfo.hasNormals,
195
+ hasUVs: geoInfo.hasUVs,
196
+ compressedOffset: geoInfo.compressedBufferOffset,
197
+ compressedSize: geoInfo.compressedBufferSize
199
198
  });
200
- const geometry = new THREE.BufferGeometry();
201
- const dataView = new DataView(dataBlob.buffer, dataBlob.byteOffset, dataBlob.byteLength);
202
- // Extract vertex positions (3 floats per vertex)
203
- if (geoInfo.vertexBufferSize > 0 && geoInfo.vertexBufferOffset + geoInfo.vertexBufferSize <= dataBlob.length) {
204
- const positions = new Float32Array(geoInfo.vertexCount * 3);
205
- for (let i = 0; i < geoInfo.vertexCount * 3; i++) {
206
- positions[i] = dataView.getFloat32(geoInfo.vertexBufferOffset + i * 4, true);
207
- }
208
- geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
209
- console.log('Added positions:', positions.slice(0, 9)); // First 3 vertices
210
- }
211
- else {
212
- console.warn('No vertex data or out of bounds');
213
- }
214
- // Extract normals
215
- if (geoInfo.normalBufferSize > 0 && geoInfo.normalBufferOffset + geoInfo.normalBufferSize <= dataBlob.length) {
216
- const normals = new Float32Array(geoInfo.vertexCount * 3);
217
- for (let i = 0; i < geoInfo.vertexCount * 3; i++) {
218
- normals[i] = dataView.getFloat32(geoInfo.normalBufferOffset + i * 4, true);
219
- }
220
- geometry.setAttribute('normal', new THREE.BufferAttribute(normals, 3));
221
- }
222
- else {
223
- // Compute normals if not provided
224
- geometry.computeVertexNormals();
225
- }
226
- // Extract UVs
227
- if (geoInfo.uvBufferSize > 0 && geoInfo.uvBufferOffset + geoInfo.uvBufferSize <= dataBlob.length) {
228
- const uvs = new Float32Array(geoInfo.vertexCount * 2);
229
- for (let i = 0; i < geoInfo.vertexCount * 2; i += 2) {
230
- uvs[i] = dataView.getFloat32(geoInfo.uvBufferOffset + i * 4, true); // U
231
- uvs[i + 1] = 1.0 - dataView.getFloat32(geoInfo.uvBufferOffset + (i + 1) * 4, true); // V (flipped)
232
- }
233
- geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2));
234
- }
235
- // Extract indices
236
- if (geoInfo.indexCount > 0 && geoInfo.indexBufferOffset + geoInfo.indexBufferSize <= dataBlob.length) {
237
- const indices = new Uint32Array(geoInfo.indexCount);
238
- // Read the first index to determine the base offset
239
- let minIndex = Number.MAX_SAFE_INTEGER;
240
- for (let i = 0; i < geoInfo.indexCount; i++) {
241
- const index = dataView.getUint32(geoInfo.indexBufferOffset + i * 4, true);
242
- if (index < minIndex)
243
- minIndex = index;
244
- }
245
- // Read indices again and offset them to start from 0
246
- for (let i = 0; i < geoInfo.indexCount; i++) {
247
- const absoluteIndex = dataView.getUint32(geoInfo.indexBufferOffset + i * 4, true);
248
- indices[i] = absoluteIndex - minIndex;
249
- }
250
- geometry.setIndex(new THREE.BufferAttribute(indices, 1));
251
- console.log(`Added indices (offset by ${minIndex}):`, indices.slice(0, 12)); // First 4 triangles
252
- }
253
- else if (geoInfo.indexCount > 0) {
254
- console.warn('Index data out of bounds');
255
- }
256
- // Ensure we have normals (compute if missing)
257
- if (!geometry.attributes.normal) {
258
- geometry.computeVertexNormals();
259
- }
199
+ // Extract the Draco compressed buffer
200
+ if (geoInfo.compressedBufferOffset + geoInfo.compressedBufferSize > dataBlob.length) {
201
+ throw new Error(`Compressed buffer out of bounds: offset=${geoInfo.compressedBufferOffset}, size=${geoInfo.compressedBufferSize}, dataLength=${dataBlob.length}`);
202
+ }
203
+ const compressedData = dataBlob.slice(geoInfo.compressedBufferOffset, geoInfo.compressedBufferOffset + geoInfo.compressedBufferSize);
204
+ // Decode using Draco
205
+ // Create a blob URL for the Draco data (DRACOLoader expects a URL)
206
+ const arrayBuffer = compressedData.buffer.slice(compressedData.byteOffset, compressedData.byteOffset + compressedData.byteLength);
207
+ const blob = new Blob([arrayBuffer]);
208
+ const url = URL.createObjectURL(blob);
209
+ const geometry = await new Promise((resolve, reject) => {
210
+ dracoLoader.load(url, (decoded) => {
211
+ URL.revokeObjectURL(url);
212
+ console.log('Draco decoded successfully:', decoded);
213
+ // UVs are pre-flipped in the packer now, no need to flip here
214
+ resolve(decoded);
215
+ }, undefined, (error) => {
216
+ URL.revokeObjectURL(url);
217
+ console.error('Draco decode failed:', error);
218
+ reject(new Error(`Failed to decode Draco geometry: ${error}`));
219
+ });
220
+ });
221
+ // Compute bounding volumes
260
222
  geometry.computeBoundingSphere();
261
223
  geometry.computeBoundingBox();
262
224
  console.log('Final geometry:', {
@@ -271,7 +233,7 @@ class MeshParser {
271
233
  /**
272
234
  * Build Three.js scene from parsed mesh data
273
235
  */
274
- static buildScene(parsedData, dataBlob) {
236
+ static async buildScene(parsedData, dataBlob, dracoLoader) {
275
237
  const root = new THREE.Group();
276
238
  root.name = 'StowKitMesh';
277
239
  const { geometries, materials, nodes, meshIndices } = parsedData;
@@ -299,7 +261,7 @@ class MeshParser {
299
261
  if (meshIndex < geometries.length) {
300
262
  const geoInfo = geometries[meshIndex];
301
263
  console.log(` Creating geometry from geoInfo: vertices=${geoInfo.vertexCount}, indices=${geoInfo.indexCount}, material=${geoInfo.materialIndex}`);
302
- const geometry = this.createGeometry(geoInfo, dataBlob);
264
+ const geometry = await this.createGeometry(geoInfo, dataBlob, dracoLoader);
303
265
  // Use assigned material if valid, otherwise create default
304
266
  let material;
305
267
  if (geoInfo.materialIndex < materials.length) {
@@ -342,9 +304,10 @@ class MeshParser {
342
304
  // If no nodes, create a single mesh from all geometries
343
305
  if (nodes.length === 0 && geometries.length > 0) {
344
306
  console.log('No nodes found, creating meshes directly from geometries');
345
- geometries.forEach((geoInfo, index) => {
307
+ for (let index = 0; index < geometries.length; index++) {
308
+ const geoInfo = geometries[index];
346
309
  console.log(`Creating direct mesh ${index}: materialIndex=${geoInfo.materialIndex}, vertices=${geoInfo.vertexCount}`);
347
- const geometry = this.createGeometry(geoInfo, dataBlob);
310
+ const geometry = await this.createGeometry(geoInfo, dataBlob, dracoLoader);
348
311
  // Use assigned material if valid, otherwise create default
349
312
  let material;
350
313
  if (geoInfo.materialIndex < materials.length) {
@@ -363,7 +326,7 @@ class MeshParser {
363
326
  mesh.name = `Mesh_${index}`;
364
327
  root.add(mesh);
365
328
  console.log(`Added mesh ${index} to root`);
366
- });
329
+ }
367
330
  }
368
331
  console.log(`Final scene has ${root.children.length} direct children`);
369
332
  // Debug: traverse and count all meshes, showing full hierarchy
@@ -430,16 +393,26 @@ class StowKitLoader extends THREE.Loader {
430
393
  this.reader = new StowKitReader(wasmPath);
431
394
  this.ownedReader = true;
432
395
  }
433
- // Setup KTX2 loader for textures with default path
434
- const transcoderPath = parameters?.transcoderPath || '/basis/';
396
+ // Setup KTX2 loader for textures with default path (user must provide basis files)
397
+ const transcoderPath = parameters?.transcoderPath || '/basis/'; // Users still need to provide this
435
398
  this.ktx2Loader = new KTX2Loader(manager);
436
399
  this.ktx2Loader.setTranscoderPath(transcoderPath);
400
+ // Setup Draco loader for mesh decompression
401
+ this.dracoLoader = new DRACOLoader(manager);
402
+ this.dracoLoader.setDecoderPath('/stowkit/draco/'); // Draco files copied by postinstall
437
403
  // Detect support with a temporary renderer
438
404
  // This is required for KTX2Loader to work
439
405
  const tempRenderer = new THREE.WebGLRenderer();
440
406
  this.ktx2Loader.detectSupport(tempRenderer);
441
407
  tempRenderer.dispose();
442
408
  }
409
+ /**
410
+ * Set the path to the Draco decoder
411
+ */
412
+ setDracoDecoderPath(path) {
413
+ this.dracoLoader.setDecoderPath(path);
414
+ return this;
415
+ }
443
416
  /**
444
417
  * Set the path to the Basis Universal transcoder
445
418
  */
@@ -469,6 +442,42 @@ class StowKitLoader extends THREE.Loader {
469
442
  const arrayBuffer = await response.arrayBuffer();
470
443
  await this.reader.open(arrayBuffer);
471
444
  }
445
+ /**
446
+ * Load and parse a mesh asset by its index
447
+ * @param index - Asset index
448
+ * @param onLoad - Callback when loading completes
449
+ * @param onProgress - Progress callback
450
+ * @param onError - Error callback
451
+ */
452
+ async loadMeshByIndex(index, onLoad, onProgress, onError) {
453
+ try {
454
+ // Read mesh data and metadata
455
+ const data = this.reader.readAssetData(index);
456
+ const metadata = this.reader.readAssetMetadata(index);
457
+ if (!data) {
458
+ throw new Error(`Failed to read mesh data for index ${index}`);
459
+ }
460
+ if (!metadata) {
461
+ throw new Error(`No metadata available for index ${index}`);
462
+ }
463
+ // Parse mesh data
464
+ const parsedData = MeshParser.parseMeshData(metadata, data);
465
+ // Load textures for materials
466
+ await this.loadMaterialTextures(parsedData.materialData, parsedData.materials);
467
+ // Build Three.js scene with Draco decoder
468
+ const scene = await MeshParser.buildScene(parsedData, data, this.dracoLoader);
469
+ if (onLoad) {
470
+ onLoad(scene);
471
+ }
472
+ return scene;
473
+ }
474
+ catch (error) {
475
+ if (onError) {
476
+ onError(error);
477
+ }
478
+ throw error;
479
+ }
480
+ }
472
481
  /**
473
482
  * Load and parse a mesh asset from a StowKit pack
474
483
  * @param url - URL to the .stow file (or omit if already opened with openPack)
@@ -501,8 +510,8 @@ class StowKitLoader extends THREE.Loader {
501
510
  const parsedData = MeshParser.parseMeshData(metadata, data);
502
511
  // Load textures for materials
503
512
  await this.loadMaterialTextures(parsedData.materialData, parsedData.materials);
504
- // Build Three.js scene
505
- const scene = MeshParser.buildScene(parsedData, data);
513
+ // Build Three.js scene with Draco decoder
514
+ const scene = await MeshParser.buildScene(parsedData, data, this.dracoLoader);
506
515
  if (onLoad) {
507
516
  onLoad(scene);
508
517
  }
@@ -738,20 +747,20 @@ class StowKitLoader extends THREE.Loader {
738
747
  if (assetIndex < 0)
739
748
  return null;
740
749
  const metadata = this.reader.readAssetMetadata(assetIndex);
741
- if (!metadata || metadata.length < 148)
742
- return null;
750
+ if (!metadata || metadata.length < 144)
751
+ return null; // TextureMetadata is now 144 bytes
743
752
  const view = new DataView(metadata.buffer, metadata.byteOffset, metadata.byteLength);
744
753
  const decoder = new TextDecoder();
745
- // Parse TextureMetadata structure
746
- const stringIdBytes = metadata.slice(20, 148);
754
+ // Parse TextureMetadata structure (width, height, channels, channel_format, string_id[128])
755
+ const stringIdBytes = metadata.slice(16, 144); // After 4 uint32s (16 bytes)
747
756
  const nullIdx = stringIdBytes.indexOf(0);
748
757
  const stringId = decoder.decode(stringIdBytes.slice(0, nullIdx >= 0 ? nullIdx : 128));
749
758
  return {
750
759
  width: view.getUint32(0, true),
751
760
  height: view.getUint32(4, true),
752
761
  channels: view.getUint32(8, true),
753
- isKtx2: view.getUint32(12, true) === 1,
754
- channelFormat: view.getUint32(16, true),
762
+ isKtx2: true, // All textures are KTX2 now
763
+ channelFormat: view.getUint32(12, true),
755
764
  stringId
756
765
  };
757
766
  }
@@ -880,8 +889,8 @@ class StowKitLoader extends THREE.Loader {
880
889
  const materialCount = view.getUint32(4, true);
881
890
  const nodeCount = view.getUint32(8, true);
882
891
  let offset = 140;
883
- // Skip geometries (76 bytes each)
884
- offset += meshGeometryCount * 76;
892
+ // Skip geometries (40 bytes each - Draco compressed)
893
+ offset += meshGeometryCount * 40;
885
894
  // Parse materials
886
895
  const materials = [];
887
896
  for (let i = 0; i < materialCount; i++) {
@@ -1002,6 +1011,7 @@ class StowKitLoader extends THREE.Loader {
1002
1011
  */
1003
1012
  dispose() {
1004
1013
  this.ktx2Loader.dispose();
1014
+ this.dracoLoader.dispose();
1005
1015
  if (this.ownedReader) {
1006
1016
  this.reader.close();
1007
1017
  }