Skip to content

Instantly share code, notes, and snippets.

@donmccurdy
Created August 5, 2018 05:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save donmccurdy/a3ec4768895069eae8cc1ab2d0ab0f1f to your computer and use it in GitHub Desktop.
Save donmccurdy/a3ec4768895069eae8cc1ab2d0ab0f1f to your computer and use it in GitHub Desktop.
CLI script for de-duplicating images references in a glTF asset.
const Listr = require('listr');
const program = require('commander');
const path = require('path');
const fs = require('fs');
const tasks = new Listr([
{
title: 'reading file',
task: (ctx) => {
if (!ctx.program.output) {
ctx.program.help();
throw new Error('Missing required output filepath.');
}
ctx.inputPath = path.normalize(ctx.program.args[0]);
ctx.outputPath = path.normalize(ctx.program.output);
ctx.gltf = JSON.parse(fs.readFileSync(ctx.inputPath, 'utf8'));
}
},
{
title: 'de-duplicating images',
task: (ctx) => {
const imageMap = ctx.imageMap = {};
const images = [];
ctx.gltf.images.forEach((imageDef, imageIndex) => {
if (!imageDef.uri) {
throw new Error('GLB assets must be unpacked before use with this tool.');
} else if (imageMap[imageDef.uri] === undefined) {
images.push(imageDef);
imageMap[imageDef.uri] = images.length - 1;
imageMap[imageIndex] = images.length - 1;
} else {
imageMap[imageIndex] = imageMap[imageDef.uri];
}
});
ctx.gltf.images = images;
}
},
{
title: 'de-duplicating textures',
task: (ctx) => {
const textureMap = ctx.textureMap = {};
const textures = [];
ctx.gltf.textures.forEach((textureDef, textureIndex) => {
textureDef.source = ctx.imageMap[textureDef.source];
const textureKey = `${textureDef.source}:${textureDef.sampler}`;
if (textureMap[textureKey] === undefined) {
textures.push(textureDef);
textureMap[textureKey] = textures.length - 1;
textureMap[textureIndex] = textures.length - 1;
} else {
textureMap[textureIndex] = textureMap[textureKey];
}
});
ctx.gltf.textures = textures;
}
},
{
title: 'updating materials',
task: (ctx) => {
ctx.gltf.materials.forEach((materialDef) => {
dedupTexture(ctx, materialDef, 'emissiveTexture');
dedupTexture(ctx, materialDef, 'normalTexture');
dedupTexture(ctx, materialDef, 'occlusionTexture');
dedupTexture(ctx, materialDef.pbrMetallicRoughness, 'baseColorTexture');
dedupTexture(ctx, materialDef.pbrMetallicRoughness, 'metallicRoughnessTexture');
const specGloss = (materialDef.extensions||{}).KHR_materials_pbrSpecularGlossiness;
if (specGloss) {
dedupTexture(ctx, specGloss, 'diffuseTexture');
dedupTexture(ctx, specGloss, 'specularGlossinessTexture');
}
});
}
},
{
title: 'writing output',
task: (ctx) => {
const json = ctx.program.pretty
? JSON.stringify(ctx.gltf, null, 2)
: JSON.stringify(ctx.gltf);
fs.writeFileSync(ctx.outputPath, json);
}
}
]);
function dedupTexture(ctx, def, name) {
if (def[name]) {
def[name].index = ctx.textureMap[def[name].index];
}
}
program
.version('0.1.0')
.usage('[options] <inputFile> -o <outputFile>')
.option('-o, --output [path]', 'output filepath')
.option('-p, --pretty', 'prettyprint JSON')
.parse(process.argv);
tasks.run({program: program});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment