@needle-tools/gltf-build-pipeline 2.7.0-alpha → 2.7.0-alpha.2

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/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ All notable changes to this package will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [2.7.0-alpha.2] - 2024-02-13
8
+ - fix: processing for some very large meshes where hashing the meshes failed (for caching the results)
9
+
10
+ ## [2.7.0-alpha.1] - 2024-01-13
11
+ - fix: handle LOD omitting and remove deleted files from progressive transform results list
12
+
7
13
  ## [2.7.0-alpha] - 2024-01-13
8
14
  - add: VRM mesh simplification support
9
15
  - fix: issue where the output directory was not created if it didn't exist yet
@@ -44,7 +44,7 @@ export declare function tryGetMetaFromCache(key: string, ignoreVersion?: boolean
44
44
  export declare function getKey(property: ExtensibleProperty): string;
45
45
  export declare function getKeyWithHash(property: ExtensibleProperty): {
46
46
  key: string;
47
- hash: number;
47
+ hash: string;
48
48
  };
49
49
  /**
50
50
  * Get the hash for a property or an object.
@@ -52,4 +52,4 @@ export declare function getKeyWithHash(property: ExtensibleProperty): {
52
52
  * @param level The current level of recursion.
53
53
  * @returns The hash as a number.
54
54
  */
55
- export declare function getHash(property: ExtensibleProperty | object, level?: number): number;
55
+ export declare function getHash(property: ExtensibleProperty | object, level?: number): string;
@@ -181,7 +181,7 @@ export function getKeyWithHash(property) {
181
181
  * @returns The hash as a number.
182
182
  */
183
183
  export function getHash(property, level = 0) {
184
- let hash = 0;
184
+ let hash = "";
185
185
  if (property instanceof ExtensibleProperty) {
186
186
  const extensions = property.listExtensions();
187
187
  const extras = property.getExtras();
@@ -209,15 +209,24 @@ export function getHash(property, level = 0) {
209
209
  const attributes = property.listAttributes();
210
210
  const targets = property.listTargets();
211
211
  // TODO: hash buffer view if possible
212
- const semantics = property.listSemantics().map(s => {
213
- return { name: s, array: property.getAttribute(s).getArray() };
212
+ const semantics = property.listSemantics();
213
+ const semanticsNames = semantics.map(s => {
214
+ return {
215
+ name: s,
216
+ };
214
217
  });
215
218
  hash += hashObject({
216
219
  indices,
217
220
  attributes,
218
221
  targets,
219
- semantics
222
+ semantics: semanticsNames
220
223
  });
224
+ // We can not pass the whole buffer into hashObject since very large meshes will cause errors when trying to stringify
225
+ // See https://linear.app/needle/issue/NE-6414
226
+ for (const sem of semantics) {
227
+ const arr = property.getAttribute(sem).getArray();
228
+ hash += hashBuffer(arr.buffer, arr.byteOffset, arr.byteLength);
229
+ }
221
230
  }
222
231
  }
223
232
  else {
@@ -236,13 +245,20 @@ function getCacheDirectory(root) {
236
245
  function hashObject(obj) {
237
246
  if (obj instanceof Accessor) {
238
247
  const buffer = obj.getArray();
239
- return hashBuffer(buffer);
248
+ return hashBuffer(buffer.buffer);
240
249
  }
241
250
  else if (obj == null) {
242
251
  return 0;
243
252
  }
244
- const str = JSON.stringify(obj);
245
- return hashString(str);
253
+ try {
254
+ const str = JSON.stringify(obj);
255
+ return hashString(str);
256
+ }
257
+ catch (err) {
258
+ console.error(err);
259
+ debugger;
260
+ throw err;
261
+ }
246
262
  }
247
263
  function hashBuffer(buffer, offset, length) {
248
264
  let hash = 0;
@@ -29,6 +29,19 @@ export async function make_progressive(opts) {
29
29
  if (!res)
30
30
  success = false;
31
31
  });
32
+ if (success) {
33
+ // Make sure all results exist
34
+ // It's possible that files were deleted while omitting LODs - we want to remove them from the results list
35
+ const resultsCount = opts.results.length;
36
+ for (let i = opts.results.length - 1; i >= 0; i--) {
37
+ if (!existsSync(opts.results[i])) {
38
+ opts.results.splice(i, 1);
39
+ }
40
+ }
41
+ const resultsChanged = resultsCount !== opts.results.length;
42
+ if (opts.debug)
43
+ console.log(`Progressive Transform: ${opts.results.length} files processed. ${resultsChanged ? "Some results were removed" : ""}`);
44
+ }
32
45
  return success;
33
46
  }
34
47
  function registerExtensions(io) {
@@ -384,12 +397,14 @@ async function createTextureLod(args, opts) {
384
397
  if (!existsSync(basePath)) {
385
398
  mkdirSync(basePath, { recursive: true });
386
399
  }
387
- logger.info(`Write texture LOD ${level} to \"${filename}\"`);
400
+ logger.info(`[${NAME}] Write texture LOD ${level} to \"${filename}\"`);
388
401
  newIo.write(outName, newDoc);
402
+ logger.info(`[${NAME}] Generate hash for texture LOD ${level}`);
403
+ const hash = getHash(newTexture);
389
404
  return {
390
405
  outpath: outName,
391
406
  texture: newTexture,
392
- hash: getHash(newTexture).toString(),
407
+ hash: hash,
393
408
  };
394
409
  }
395
410
  function createMeshForMaterial(doc, mat, i) {
@@ -661,7 +676,7 @@ export function make_progressive_meshes(filePath, _options, opts) {
661
676
  if (shouldOmitLevel) {
662
677
  logger.debug(`[${NAME}] Omitting LOD ${level} for \"${mesh.getName()}\" at \"${lodInfo.path}\"`);
663
678
  generatedLODInfos.splice(i, 1);
664
- rmSync(fullPath);
679
+ deleteFile(fullPath, opts);
665
680
  i--;
666
681
  }
667
682
  else {
@@ -699,7 +714,7 @@ export function make_progressive_meshes(filePath, _options, opts) {
699
714
  logger.info(`[${NAME}]: Flag mesh LOD ${generatedLODInfos.length} (embedded): vertex count difference below threshold (removed ${difference} vertices, ${(-diff01 * 100).toFixed(2)} %) → will remove all LODs. \"${mesh.getName()}\"`);
700
715
  try {
701
716
  for (const lodInfo of generatedLODInfos) {
702
- rmSync(outputDirectory + "/" + lodInfo.path);
717
+ deleteFile(outputDirectory + "/" + lodInfo.path, opts);
703
718
  }
704
719
  }
705
720
  catch (err) {
@@ -744,6 +759,9 @@ export function make_progressive_meshes(filePath, _options, opts) {
744
759
  }
745
760
  });
746
761
  }
762
+ function deleteFile(filePath, _context) {
763
+ rmSync(filePath);
764
+ }
747
765
  function clonePrimitiveData(prim, logger) {
748
766
  const semantics = prim.listSemantics();
749
767
  if (semantics.some(s => s.includes("JOINTS"))) {
@@ -791,6 +809,7 @@ async function createMeshLod(inputFileName, doc, basePath, level, mesh, meshInfo
791
809
  // generate hash for mesh
792
810
  let hash = mesh["needle:mesh-hash"];
793
811
  if (hash === undefined) {
812
+ logger.info(`[${NAME}] Generating hash for mesh \"${mesh.getName()}\"`);
794
813
  hash = getHash(mesh);
795
814
  mesh["needle:mesh-hash"] = hash;
796
815
  }
@@ -1 +1 @@
1
- export declare const version = "2.7.0-alpha";
1
+ export declare const version = "2.7.0-alpha.2";
@@ -1 +1 @@
1
- export const version = "2.7.0-alpha";
1
+ export const version = "2.7.0-alpha.2";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/gltf-build-pipeline",
3
- "version": "2.7.0-alpha",
3
+ "version": "2.7.0-alpha.2",
4
4
  "description": "Pipeline and tools for optimizing gltf files using gltf-transform and compression settings within glTF extensions",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -24,7 +24,8 @@
24
24
  "scripts": {
25
25
  "start": "node scripts/index.mjs",
26
26
  "dev": "npm-watch compile",
27
- "publish": "npm run compile && npm publish --access public",
27
+ "publish": "npm run compile && npm publish --access public --tag alpha",
28
+ "publish-tag": "npm dist-tag add @needle-tools/gltf-build-pipeline@2.7.0-alpha.1 alpha",
28
29
  "compile": "node tools/prebuild.mjs && (tsc || exit 1) && node tools/postbuild.mjs",
29
30
  "clear-caches": "node scripts/clear-caches.mjs",
30
31
  "limit-caches": "node scripts/limit-caches.mjs",