@needle-tools/gltf-build-pipeline 2.15.1 → 2.15.3

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/cli/index.js CHANGED
@@ -172,6 +172,9 @@ Each version will be compressed and written to the output directory.
172
172
  verbose,
173
173
  useCache,
174
174
  logger: logger,
175
+ // When progressive ran first, inputFile points to the progressive output copy.
176
+ // Pass the original source path so extensions can resolve sibling assets (e.g. .exr files).
177
+ sourceFile: progressive_results.length > 0 ? file : undefined,
175
178
  };
176
179
  // If we have produced progressive assets then the array already contains the input
177
180
  if (progressive_results.length > 0) {
@@ -9,6 +9,8 @@ export type PackGLTFOptions = {
9
9
  logger?: ILogger;
10
10
  debug: boolean;
11
11
  verbose?: boolean;
12
+ /** Original source file path, used to resolve external assets (e.g. .exr files) when inputFile differs from the source (e.g. after progressive transform) */
13
+ sourceFile?: string;
12
14
  };
13
15
  /** Compress a glTF file
14
16
  */
@@ -49,7 +49,7 @@ export async function packGLTF(inputFile, outputFile, options) {
49
49
  outputFile = getOutputPath(inputFile, outputFile);
50
50
  }
51
51
  const prevSizeInMB = statSync(inputFile).size / 1024 / 1024;
52
- logger.info(`→ Compressing ${prevSizeInMB.toFixed(1)} MB: ${inputFile}`);
52
+ logger.debug(`→ Compressing ${prevSizeInMB.toFixed(1)} MB: ${inputFile}`);
53
53
  const startTime = Date.now();
54
54
  const io = new NodeIO()
55
55
  .registerExtensions(ALL_EXTENSIONS)
@@ -67,8 +67,10 @@ export async function packGLTF(inputFile, outputFile, options) {
67
67
  'meshopt.encoder': MeshoptEncoder,
68
68
  });
69
69
  // Set input file path so extensions can resolve external EXR files
70
- NEEDLE_lightmaps_ext.inputFile = inputFile;
71
- setOpaqueInputFile(inputFile);
70
+ // Use sourceFile when available (e.g. when inputFile is a progressive output copy)
71
+ const assetSourceFile = options.sourceFile ?? inputFile;
72
+ NEEDLE_lightmaps_ext.inputFile = assetSourceFile;
73
+ setOpaqueInputFile(assetSourceFile);
72
74
  const document = await ioTryReadWithMissingResources(io, inputFile);
73
75
  if (options.logger) {
74
76
  document.setLogger(options.logger);
@@ -121,7 +123,7 @@ export async function packGLTF(inputFile, outputFile, options) {
121
123
  }));
122
124
  }
123
125
  await document.transform(...transforms);
124
- logger.info(`← Writing to ${outputFile}`);
126
+ logger.debug(`← Writing to ${outputFile}`);
125
127
  await writeNodeIO(io, outputFile, document);
126
128
  if (useCache && cacheKey != undefined && existsSync(outputFile))
127
129
  addToCache(cacheKey, readFileSync(outputFile));
@@ -129,7 +131,7 @@ export async function packGLTF(inputFile, outputFile, options) {
129
131
  const sizeInMB = statSync(outputFile).size / 1024 / 1024;
130
132
  const filename = path.basename(outputFile);
131
133
  const gpuMemoryInMB = totalGPUTextureMemory / 1024 / 1024;
132
- logger.info(`← Compressing done in ${(duration / 1000).toFixed(1)} sec, ${prevSizeInMB.toFixed(1)} MB → ${sizeInMB.toFixed(1)} MB (GPU: ${gpuMemoryInMB.toFixed(1)} MB textures): ${filename} at ${outputFile}`);
134
+ logger.info(`← Compressed '${filename}' ${prevSizeInMB.toFixed(1)} MB → ${sizeInMB.toFixed(1)} MB (GPU: ${gpuMemoryInMB.toFixed(1)} MB textures) in ${(duration / 1000).toFixed(1)} sec`);
133
135
  if (stats) {
134
136
  stats.totalFilesProcessed++;
135
137
  stats.totalFileSizeInMB += sizeInMB;
@@ -41,7 +41,7 @@ export function determineMeshCompression(document, filePath) {
41
41
  }
42
42
  // TODO: make this more robus with progressive loading: when progressive loading is enabled we need to run this check on the root mesh and enforce the same mesh compression for all children. Until we can do that we can not use the code for choosing compression based on blendshape size
43
43
  if (sizeOfBlendshapes > 0) {
44
- document.getLogger().info(`[${NAME}]: will apply meshopt mesh compression because the mesh contains blendshapes`);
44
+ document.getLogger().debug(`[${NAME}]: will apply meshopt mesh compression because the mesh contains blendshapes`);
45
45
  return new NEEDLE_mesh_compression_model_root("meshopt");
46
46
  }
47
47
  // consider meshopt if blendshape size is > 256 KB
@@ -52,7 +52,7 @@ export function determineMeshCompression(document, filePath) {
52
52
  // /** 25% of the size are blendshapres */
53
53
  // const ratioThreshold = 0.1;
54
54
  // if (blendshapeRatio >= ratioThreshold) {
55
- // document.getLogger().info(`[${NAME}]: will apply meshopt mesh compression because blendshapes are ${(blendshapeRatio * 100).toFixed(2)}% of the mesh size`);
55
+ // document.getLogger().debug(`[${NAME}]: will apply meshopt mesh compression because blendshapes are ${(blendshapeRatio * 100).toFixed(2)}% of the mesh size`);
56
56
  // const transform = meshopt({ encoder: MeshoptEncoder });
57
57
  // return transform(document, transform_context);
58
58
  // }
@@ -73,10 +73,10 @@ async function applyMeshCompression(document, transform_context, context) {
73
73
  // const rootModel = rootExtension.model as NEEDLE_mesh_compression_model_root;
74
74
  if (compressionModel.compression) {
75
75
  if (compressionModel.compression === "none") {
76
- document.getLogger().info(`[${NAME}]: NONE → will not apply mesh compression`);
76
+ document.getLogger().debug(`[${NAME}]: NONE → will not apply mesh compression`);
77
77
  return;
78
78
  }
79
- document.getLogger().info(`[${NAME}]: ${compressionModel.compression.toUpperCase()} → will apply ${compressionModel.compression} mesh compression`);
79
+ document.getLogger().debug(`[${NAME}]: ${compressionModel.compression.toUpperCase()} → will apply ${compressionModel.compression} mesh compression`);
80
80
  if (compressionModel.compression === "draco") {
81
81
  const transform = draco({
82
82
  encodeSpeed: 8,
@@ -92,7 +92,7 @@ async function applyMeshCompression(document, transform_context, context) {
92
92
  }
93
93
  }
94
94
  // by default we still want to run draco if the root doesnt have a compression model configured
95
- document.getLogger().info(`[${NAME}]: → will apply draco mesh compression (default)`);
95
+ document.getLogger().debug(`[${NAME}]: → will apply draco mesh compression (default)`);
96
96
  const transform = draco({
97
97
  encodeSpeed: 8,
98
98
  decodeSpeed: 8,
@@ -103,7 +103,7 @@ async function applyMeshCompression(document, transform_context, context) {
103
103
  async function simplifierTransform(document, _context, meshContext) {
104
104
  const simplifier = MeshoptSimplifier;
105
105
  if (!simplifier) {
106
- console.log(`WARN: [${NAME}] simplifier dependency required — install "meshoptimizer".`);
106
+ document.getLogger().warn(`WARN: [${NAME}] simplifier dependency required — install "meshoptimizer".`);
107
107
  return false;
108
108
  }
109
109
  const logger = document.getLogger();
@@ -213,7 +213,7 @@ export function make_progressive_textures(filePath, _options = TEXTURE_RESIZE_DE
213
213
  logger.debug(`[${NAME}] Skipping because progressive extension is not available. ${textureIndex}`);
214
214
  continue;
215
215
  }
216
- const mimeTypeResult = validateImageMimeType(texture.getMimeType(), texture.getImage());
216
+ const mimeTypeResult = validateImageMimeType(texture.getMimeType(), texture.getImage(), logger);
217
217
  if (mimeTypeResult?.error) {
218
218
  logger.warn(`[${NAME}] Texture[${index}] has invalid mime type! Reported \"${texture.getMimeType()}\" but is actually \"${mimeTypeResult.mimeType}\": auto-fix`);
219
219
  texture.setMimeType(mimeTypeResult.mimeType);
@@ -514,7 +514,7 @@ export async function resizeTextureToMax(texture, maxSize, logger) {
514
514
  await resizeTexture(options, texture, logger);
515
515
  }
516
516
  async function resizeTexture(options, texture, logger, uri, slots) {
517
- const mimeTypeResult = validateImageMimeType(texture.getMimeType(), texture.getImage());
517
+ const mimeTypeResult = validateImageMimeType(texture.getMimeType(), texture.getImage(), logger);
518
518
  if (mimeTypeResult?.error) {
519
519
  logger.warn(`[${NAME}] Texture[${uri}] has invalid mime type: ${mimeTypeResult.error}: auto-fix`);
520
520
  texture.setMimeType(mimeTypeResult.mimeType);
@@ -88,7 +88,7 @@ export const needle_texture_transform = function (options) {
88
88
  });
89
89
  };
90
90
  async function processTexture(texture, index, document, logger, context) {
91
- const validationResult = validateImageMimeType(texture.getMimeType(), texture.getImage());
91
+ const validationResult = validateImageMimeType(texture.getMimeType(), texture.getImage(), logger);
92
92
  if (validationResult?.error) {
93
93
  logger.warn(`WARN: Texture ${texture.getName()} [${index}] has an incorrect mime type \"${texture.getMimeType()}\" → auto-correcting to ${validationResult.mimeType}`);
94
94
  texture.setMimeType(validationResult.mimeType);
@@ -1,4 +1,5 @@
1
- export declare function validateImageMimeType(mimetype: string, image: Uint8Array): {
1
+ import { ILogger } from "@gltf-transform/core";
2
+ export declare function validateImageMimeType(mimetype: string, image: Uint8Array, logger: ILogger): {
2
3
  error: boolean;
3
4
  message: string;
4
5
  mimeType: string;
@@ -1,9 +1,9 @@
1
1
  import { ImageUtils } from "@gltf-transform/core";
2
- export function validateImageMimeType(mimetype, image) {
2
+ export function validateImageMimeType(mimetype, image, logger) {
3
3
  const actualMimeType = ImageUtils.getMimeType(image);
4
4
  if (actualMimeType != null && actualMimeType != mimetype) {
5
5
  const msg = `Image reported wrong mime type \"${mimetype}\" but is actually \"${actualMimeType}\"`;
6
- console.error(`WARN: ${msg}`);
6
+ logger.warn(msg);
7
7
  return {
8
8
  error: true,
9
9
  message: msg,
@@ -11,7 +11,7 @@ export function validateImageMimeType(mimetype, image) {
11
11
  };
12
12
  }
13
13
  else if (actualMimeType === null) {
14
- console.warn(`WARN: Could not validate image type: \"${mimetype}\"`);
14
+ logger.debug(`Could not validate image type: \"${mimetype}\"`);
15
15
  }
16
16
  return null;
17
17
  }
@@ -1 +1 @@
1
- export declare const version = "2.15.1";
1
+ export declare const version = "2.15.3";
@@ -1 +1 @@
1
- export const version = "2.15.1";
1
+ export const version = "2.15.3";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/gltf-build-pipeline",
3
- "version": "2.15.1",
3
+ "version": "2.15.3",
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",