@needle-tools/gltf-build-pipeline 2.14.0 → 2.15.0-next.a25e7ea
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/cache/cache.js +4 -4
- package/dist/cli/index.js +0 -0
- package/dist/extensions/NEEDLE_opaque/NEEDLE_opaque.js +38 -26
- package/dist/scripts/pack-gltf.js +2 -1
- package/dist/transforms/needle_progressive.js +12 -3
- package/dist/utils/version.gen.d.ts +1 -1
- package/dist/utils/version.gen.js +1 -1
- package/package.json +1 -1
package/dist/cache/cache.js
CHANGED
|
@@ -5,9 +5,9 @@ import path from 'path';
|
|
|
5
5
|
import { getVersion } from "../utils/version.js";
|
|
6
6
|
// import * as CHECKDISCSPACE from 'check-disk-space'
|
|
7
7
|
import xxhash from "xxhash-wasm";
|
|
8
|
-
let
|
|
8
|
+
let xxHashModule = null;
|
|
9
9
|
xxhash().then(module => {
|
|
10
|
-
|
|
10
|
+
xxHashModule = module;
|
|
11
11
|
});
|
|
12
12
|
/**
|
|
13
13
|
* Get the available space on the cache directory in bytes.
|
|
@@ -304,9 +304,9 @@ function hashObject(obj, depth = 0) {
|
|
|
304
304
|
}
|
|
305
305
|
}
|
|
306
306
|
function hashBuffer(buffer, offset, length) {
|
|
307
|
-
if (
|
|
307
|
+
if (xxHashModule) {
|
|
308
308
|
const view = new Uint8Array(buffer, offset, length);
|
|
309
|
-
return
|
|
309
|
+
return xxHashModule.h32Raw(view);
|
|
310
310
|
}
|
|
311
311
|
let hash = 0;
|
|
312
312
|
const view = new Uint8Array(buffer, offset, length);
|
package/dist/cli/index.js
CHANGED
|
File without changes
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Extension, ExtensionProperty, PropertyType, Node, TextureChannel } from '@gltf-transform/core';
|
|
2
2
|
import { getTexture, tryGetInArray, writeExtension } from '../utils.js';
|
|
3
3
|
import { isLightmap } from '../../utils/texture.js';
|
|
4
|
+
import { NEEDLE_progressive_texture_settings } from '../NEEDLE_progressive_texture_settings/index.js';
|
|
4
5
|
const ALL_PROPERTY_TYPES = [];
|
|
5
6
|
for (const key in PropertyType) {
|
|
6
7
|
ALL_PROPERTY_TYPES.push(PropertyType[key]);
|
|
@@ -123,8 +124,11 @@ export function createOpaqueExtension(name, types, opts) {
|
|
|
123
124
|
const prop = this.createExtension();
|
|
124
125
|
this.jsonPointerHandler.read(context, texture, ext, prop);
|
|
125
126
|
texture.setExtension(EXTENSION_NAME, prop);
|
|
126
|
-
const handler = new TextureHandler(this.document, textureDefinition, EXTENSION_NAME, ext, debugLog);
|
|
127
|
+
const handler = new TextureHandler(this.document, textureDefinition, EXTENSION_NAME, ext, debugLog, texture);
|
|
127
128
|
prop.add(handler);
|
|
129
|
+
const sourceIndex = textureDefinition.source;
|
|
130
|
+
if (debugLog)
|
|
131
|
+
console.log("Found texture with extension", EXTENSION_NAME, "at index", index, "source image index", sourceIndex, "name", texture.getName() || "<unnamed>");
|
|
128
132
|
});
|
|
129
133
|
break;
|
|
130
134
|
case PropertyType.NODE:
|
|
@@ -188,11 +192,11 @@ export function createOpaqueExtension(name, types, opts) {
|
|
|
188
192
|
const textures = this.document.getRoot().listTextures();
|
|
189
193
|
for (let i = 0; i < textures.length; i++) {
|
|
190
194
|
const tex = textures[i];
|
|
191
|
-
const texDef = textureDefinitions[i];
|
|
192
|
-
const name = texDef?.name;
|
|
193
195
|
if (isLightmap(tex) && tex.getMimeType() !== "image/exr") {
|
|
194
196
|
prop.setReference("lightmapTexture", tex, { channels: TextureChannel.R | TextureChannel.G | TextureChannel.B | TextureChannel.A });
|
|
195
|
-
|
|
197
|
+
const texDef = textureDefinitions[i]; // @TODO: textureDefinitions and textures might not be in the same order - we need to find the texture by source index instead of assuming the order is the same
|
|
198
|
+
const name = tex.getName() || texDef?.name;
|
|
199
|
+
logger.info(`Found lightmap texture \"${name}\" (${tex.getMimeType()}) in ${EXTENSION_NAME}`);
|
|
196
200
|
}
|
|
197
201
|
}
|
|
198
202
|
}
|
|
@@ -389,30 +393,38 @@ class GenericWriter {
|
|
|
389
393
|
class TextureHandler {
|
|
390
394
|
document;
|
|
391
395
|
textureDefinition;
|
|
392
|
-
index;
|
|
393
396
|
key;
|
|
394
397
|
ext;
|
|
395
398
|
debug = false;
|
|
399
|
+
/** Reference to the gltf-transform Texture object, used to resolve the current image index at write time via imageIndexMap */
|
|
400
|
+
textureRef;
|
|
396
401
|
assignTo(obj) {
|
|
397
402
|
Object.assign(obj, this.ext);
|
|
398
403
|
}
|
|
399
|
-
constructor(doc, def, key, ext, debug) {
|
|
404
|
+
constructor(doc, def, key, ext, debug, textureRef) {
|
|
400
405
|
this.document = doc;
|
|
401
406
|
this.textureDefinition = def;
|
|
402
407
|
this.key = key;
|
|
403
408
|
this.ext = ext;
|
|
404
409
|
this.debug = debug;
|
|
405
|
-
this.
|
|
406
|
-
if (debug)
|
|
407
|
-
|
|
410
|
+
this.textureRef = textureRef;
|
|
411
|
+
if (debug) {
|
|
412
|
+
const index = this.tryGetSourceIndex(this.textureDefinition);
|
|
413
|
+
console.log(index, this.textureDefinition);
|
|
414
|
+
}
|
|
408
415
|
}
|
|
409
416
|
write(ctx) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
const imageIndex =
|
|
417
|
+
// Resolve the current image index from the gltf-transform graph reference.
|
|
418
|
+
// This is stable even after dedup/prune operations that re-index images.
|
|
419
|
+
const imageIndex = ctx.imageIndexMap.get(this.textureRef);
|
|
413
420
|
if (imageIndex === undefined) {
|
|
414
|
-
|
|
421
|
+
if (this.key !== "EXT_texture_exr" && this.debug) {
|
|
422
|
+
console.warn("WARN: failed to resolve image index for texture via imageIndexMap:", this.key, this.textureRef.getName() || "<unnamed>");
|
|
423
|
+
}
|
|
424
|
+
return;
|
|
415
425
|
}
|
|
426
|
+
let foundTexture = false;
|
|
427
|
+
const textureDefs = ctx.jsonDoc.json.textures || [];
|
|
416
428
|
textureDefs?.forEach((textureDef, i) => {
|
|
417
429
|
if (foundTexture)
|
|
418
430
|
return;
|
|
@@ -432,17 +444,10 @@ class TextureHandler {
|
|
|
432
444
|
}
|
|
433
445
|
});
|
|
434
446
|
if (foundTexture === false) {
|
|
435
|
-
if (this.key !== "EXT_texture_exr" && this.debug)
|
|
436
|
-
console.warn("WARN: failed to re-assign extension:", this.key,
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
// .getRoot()
|
|
440
|
-
// .listTextures()
|
|
441
|
-
// .forEach((texture, index) => {
|
|
442
|
-
// if (foundTexture) return;
|
|
443
|
-
// if (!texture.getExtension(this.key)) return;
|
|
444
|
-
// const imageIndex = ctx.imageIndexMap.get(texture);
|
|
445
|
-
// });
|
|
447
|
+
if (this.key !== "EXT_texture_exr" && this.debug) {
|
|
448
|
+
console.warn("WARN: failed to re-assign extension:", this.key, "imageIndex", imageIndex, textureDefs.length, this.textureRef.getName() || "<unnamed>", this.textureDefinition);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
446
451
|
}
|
|
447
452
|
tryGetSourceIndex(def) {
|
|
448
453
|
let index = def.source;
|
|
@@ -878,11 +883,18 @@ class TextureIndexResolver extends PointerResolver {
|
|
|
878
883
|
// create a new texture def entry
|
|
879
884
|
if (this.debug)
|
|
880
885
|
console.log("Could not find texture, creating a new one: " + this._debugName);
|
|
881
|
-
|
|
886
|
+
// Remove settings-only extensions that are consumed during processing and should not appear in the output.
|
|
887
|
+
let extensions = this.inputDefinition.extensions ? { ...this.inputDefinition.extensions } : undefined;
|
|
888
|
+
if (extensions) {
|
|
889
|
+
delete extensions[NEEDLE_progressive_texture_settings.EXTENSION_NAME];
|
|
890
|
+
if (Object.keys(extensions).length === 0)
|
|
891
|
+
extensions = undefined;
|
|
892
|
+
}
|
|
893
|
+
const hasExtensionWithSource = extensions && Object.keys(extensions).some(key => extensions[key]?.["source"] !== undefined);
|
|
882
894
|
const textureDef = {
|
|
883
895
|
source: hasExtensionWithSource ? undefined : imgIndex,
|
|
884
896
|
sampler: this.findOrCreateSampler(context.jsonDoc.json),
|
|
885
|
-
extensions:
|
|
897
|
+
extensions: extensions,
|
|
886
898
|
extras: this.inputDefinition.extras,
|
|
887
899
|
};
|
|
888
900
|
context.jsonDoc.json.textures.push(textureDef);
|
|
@@ -128,7 +128,8 @@ export async function packGLTF(inputFile, outputFile, options) {
|
|
|
128
128
|
return true;
|
|
129
129
|
}
|
|
130
130
|
catch (err) {
|
|
131
|
-
|
|
131
|
+
const shortedStackTrace = err instanceof Error && err.stack ? err.stack.split('\n').slice(0, 2).join('\n') : '';
|
|
132
|
+
logger.error(`Packing of "${path.basename(inputFile)}" using version ${getVersion()} failed with error:\n${err.message}\n${shortedStackTrace}`);
|
|
132
133
|
if (debug)
|
|
133
134
|
throw err;
|
|
134
135
|
return false;
|
|
@@ -151,6 +151,7 @@ export function make_progressive_textures(filePath, _options = TEXTURE_RESIZE_DE
|
|
|
151
151
|
return Promise.resolve();
|
|
152
152
|
}
|
|
153
153
|
let index = 0;
|
|
154
|
+
const textureHashCache = new Map();
|
|
154
155
|
for (const texture of doc.getRoot().listTextures()) {
|
|
155
156
|
const textureIndex = index++;
|
|
156
157
|
const name = texture.getName();
|
|
@@ -177,8 +178,10 @@ export function make_progressive_textures(filePath, _options = TEXTURE_RESIZE_DE
|
|
|
177
178
|
continue;
|
|
178
179
|
}
|
|
179
180
|
else {
|
|
181
|
+
if (!textureHashCache.has(texture))
|
|
182
|
+
textureHashCache.set(texture, getHash(texture));
|
|
180
183
|
settings = {
|
|
181
|
-
guid: generateGuid(
|
|
184
|
+
guid: generateGuid(textureHashCache.get(texture)),
|
|
182
185
|
maxSize: _options.size[0],
|
|
183
186
|
};
|
|
184
187
|
logger.debug(`[${NAME}] No settings found for texture[${index}] - will use default settings (maxSize: ${settings.maxSize}, guid: ${settings.guid})`);
|
|
@@ -213,7 +216,13 @@ export function make_progressive_textures(filePath, _options = TEXTURE_RESIZE_DE
|
|
|
213
216
|
logger.debug(`[${NAME}] Skipping, texture[${textureIndex}] is already smaller than the requested size: ${currentSize}px <= ${settings.maxSize}px`);
|
|
214
217
|
continue;
|
|
215
218
|
}
|
|
216
|
-
|
|
219
|
+
if (!settings.guid?.length) {
|
|
220
|
+
if (!textureHashCache.has(texture))
|
|
221
|
+
textureHashCache.set(texture, getHash(texture));
|
|
222
|
+
const hash = textureHashCache.get(texture);
|
|
223
|
+
settings.guid = generateGuid(hash);
|
|
224
|
+
}
|
|
225
|
+
const textureGuid = settings.guid;
|
|
217
226
|
/** This is the size of the texture that is embedded in the glTF. No LOD should be smaller than this */
|
|
218
227
|
const maxSize = settings.maxSize;
|
|
219
228
|
const LOD_LEVEL = new Array();
|
|
@@ -524,7 +533,7 @@ async function resizeTexture(options, texture, logger, uri, slots) {
|
|
|
524
533
|
}
|
|
525
534
|
dstWidth = Math.floor(dstWidth);
|
|
526
535
|
dstHeight = Math.floor(dstHeight);
|
|
527
|
-
logger.info(`→ Resize texture (${uri || texture.getName() || slots
|
|
536
|
+
logger.info(`→ Resize texture (${uri || texture.getName() || slots?.join(", ")}) from ${srcWidth}x${srcHeight} to ${dstWidth}x${dstHeight}px`);
|
|
528
537
|
// https://sharp.pixelplumbing.com/api-resize
|
|
529
538
|
const buffer = await sharp(texture.getImage())
|
|
530
539
|
.resize(dstWidth, dstHeight, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "2.
|
|
1
|
+
export declare const version = "2.15.0-next.a25e7ea";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = "2.
|
|
1
|
+
export const version = "2.15.0-next.a25e7ea";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needle-tools/gltf-build-pipeline",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.15.0-next.a25e7ea",
|
|
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",
|