Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

gltf-pipeline

Package Overview
Dependencies
Maintainers
5
Versions
45
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gltf-pipeline - npm Package Compare versions

Comparing version 3.0.5 to 4.0.1

13

bin/gltf-pipeline.js

@@ -79,2 +79,8 @@ #!/usr/bin/env node

},
keepLegacyExtensions: {
describe:
"When false, materials with KHR_techniques_webgl, KHR_blend, or KHR_materials_common will be converted to PBR.",
type: "boolean",
default: defaults.keepLegacyExtensions,
},
"draco.compressMeshes": {

@@ -144,3 +150,3 @@ alias: "d",

if (inputExtension !== ".gltf" && inputExtension !== ".glb") {
console.log('Error: unrecognized file extension "' + inputExtension + '".');
console.log(`Error: unrecognized file extension "${inputExtension}".`);
return;

@@ -160,3 +166,3 @@ }

inputDirectory,
inputName + "-processed" + outputExtension
`${inputName}-processed${outputExtension}`
);

@@ -169,3 +175,3 @@ }

if (outputExtension !== ".gltf" && outputExtension !== ".glb") {
console.log('Error: unrecognized file extension "' + outputExtension + '".');
console.log(`Error: unrecognized file extension "${outputExtension}".`);
return;

@@ -190,2 +196,3 @@ }

keepUnusedElements: argv.keepUnusedElements,
keepLegacyExtensions: argv.keepLegacyExtensions,
name: outputName,

@@ -192,0 +199,0 @@ dracoOptions: dracoOptions,

# Change Log
### 4.0.1 - 2023-01-25
- Fixed crash when writing GLB files above 2GB. [#627](https://github.com/CesiumGS/gltf-pipeline/pull/627)
### 4.0.0 - 2022-08-01
- Breaking changes
- glTF 1.0 or glTF 2.0 with the `KHR_techniques_webgl`, `KHR_blend`, or `KHR_materials_common` extensions will be converted to glTF 2.0 with PBR materials by default. For the previous behavior pass in `--keepLegacyExtensions`.
### 3.0.5 - 2022-06-30

@@ -4,0 +13,0 @@

@@ -90,4 +90,2 @@ "use strict";

values.transparency = defaultValue(values.transparency, 1.0);
values.transparent = defaultValue(values.transparent, false);
values.doubleSided = defaultValue(values.doubleSided, false);

@@ -105,2 +103,13 @@ if (technique !== "CONSTANT") {

}
// These actually exist on the extension object, not the values object despite what's shown in the spec
materialsCommon.transparent = defaultValue(
materialsCommon.transparent,
false
);
materialsCommon.doubleSided = defaultValue(
materialsCommon.doubleSided,
false
);
return;

@@ -107,0 +116,0 @@ }

@@ -94,3 +94,3 @@ "use strict";

checkRange(
"quantizationBitsValues[" + attributeName + "]",
`quantizationBitsValues[${attributeName}]`,
quantizationBitsValues[attributeName],

@@ -232,3 +232,3 @@ 0,

throw new RuntimeError(
"Error: Failed adding attribute " + semantic
`Error: Failed adding attribute ${semantic}`
);

@@ -235,0 +235,0 @@ } else {

@@ -65,3 +65,3 @@ "use strict";

const materialsCommon = material.extensions.KHR_materials_common;
if (defined(materialsCommon)) {
if (defined(materialsCommon) && defined(materialsCommon.values)) {
const diffuse = materialsCommon.values.diffuse;

@@ -68,0 +68,0 @@ const ambient = materialsCommon.values.ambient;

@@ -184,22 +184,5 @@ "use strict";

return (
"Total byte length of all buffers: " +
this.buffersByteLength +
" bytes" +
"\nImages: " +
this.numberOfImages +
"\nDraw calls: " +
this.numberOfDrawCalls +
"\nRendered primitives (e.g., triangles): " +
this.numberOfRenderedPrimitives +
"\nNodes: " +
this.numberOfNodes +
"\nMeshes: " +
this.numberOfMeshes +
"\nMaterials: " +
this.numberOfMaterials +
"\nAnimations: " +
this.numberOfAnimations +
"\nExternal requests (not data uris): " +
this.numberOfExternalRequests
`Total byte length of all buffers: ${this.buffersByteLength} bytes` +
`\nImages: ${this.numberOfImages}\nDraw calls: ${this.numberOfDrawCalls}\nRendered primitives (e.g., triangles): ${this.numberOfRenderedPrimitives}\nNodes: ${this.numberOfNodes}\nMeshes: ${this.numberOfMeshes}\nMaterials: ${this.numberOfMaterials}\nAnimations: ${this.numberOfAnimations}\nExternal requests (not data uris): ${this.numberOfExternalRequests}`
);
};
"use strict";
const BUFFER_MAX_BYTE_LENGTH = require("buffer").constants.MAX_LENGTH;
const FS_WRITE_MAX_LENGTH = 2147479552; // See https://github.com/nodejs/node/issues/35605
const BUFFER_MAX_LENGTH = require("buffer").constants.MAX_LENGTH;
const BUFFER_MAX_BYTE_LENGTH = Math.min(FS_WRITE_MAX_LENGTH, BUFFER_MAX_LENGTH);
const Cesium = require("cesium");

@@ -50,3 +52,3 @@ const ForEach = require("./ForEach");

// Prevent empty meshopt buffer from being merged into main buffer
buffer.extras._pipeline.mergedBufferName = "meshopt-fallback-" + bufferId;
buffer.extras._pipeline.mergedBufferName = `meshopt-fallback-${bufferId}`;
}

@@ -71,3 +73,3 @@ });

mergedName = defined(mergedName)
? baseBufferName + "-" + mergedName
? `${baseBufferName}-${mergedName}`
: baseBufferName;

@@ -79,3 +81,3 @@

}
mergedName += "-" + mergedNameCount[mergedName]++;
mergedName += `-${mergedNameCount[mergedName]++}`;
}

@@ -82,0 +84,0 @@

@@ -128,3 +128,5 @@ "use strict";

const uniformName = mappedUniforms[material.technique][parameterName];
materialExtension.values[uniformName] = value;
if (defined(uniformName)) {
materialExtension.values[uniformName] = value;
}
});

@@ -131,0 +133,0 @@

@@ -132,2 +132,8 @@ "use strict";

/**
* When false, materials with KHR_techniques_webgl, KHR_blend, or KHR_materials_common will be converted to PBR.
* @type Boolean
* @default false
*/
keepLegacyExtensions: false,
/**
* Gets or sets whether to compress the meshes using Draco. Adds the KHR_draco_mesh_compression extension.

@@ -134,0 +140,0 @@ * @type Boolean

@@ -127,3 +127,3 @@ "use strict";

throw new RuntimeError(
"Draco decoding failed: " + decodingStatus.error_msg()
`Draco decoding failed: ${decodingStatus.error_msg()}`
);

@@ -189,4 +189,5 @@ }

throw new RuntimeError(
"Could not get attribute data for id:" +
attribute.unique_id().toString()
`Could not get attribute data for id:${attribute
.unique_id()
.toString()}`
);

@@ -205,4 +206,5 @@ }

throw new RuntimeError(
"Could not get attribute data for id:" +
attribute.unique_id().toString()
`Could not get attribute data for id:${attribute
.unique_id()
.toString()}`
);

@@ -221,4 +223,5 @@ }

throw new RuntimeError(
"Could not get attribute data for id:" +
attribute.unique_id().toString()
`Could not get attribute data for id:${attribute
.unique_id()
.toString()}`
);

@@ -237,4 +240,5 @@ }

throw new RuntimeError(
"Could not get attribute data for id:" +
attribute.unique_id().toString()
`Could not get attribute data for id:${attribute
.unique_id()
.toString()}`
);

@@ -253,4 +257,5 @@ }

throw new RuntimeError(
"Could not get attribute data for id:" +
attribute.unique_id().toString()
`Could not get attribute data for id:${attribute
.unique_id()
.toString()}`
);

@@ -269,4 +274,5 @@ }

throw new RuntimeError(
"Could not get attribute data for id:" +
attribute.unique_id().toString()
`Could not get attribute data for id:${attribute
.unique_id()
.toString()}`
);

@@ -285,4 +291,5 @@ }

throw new RuntimeError(
"Could not get attribute data for id:" +
attribute.unique_id().toString()
`Could not get attribute data for id:${attribute
.unique_id()
.toString()}`
);

@@ -289,0 +296,0 @@ }

@@ -13,2 +13,3 @@ "use strict";

const updateAccessorComponentTypes = require("./updateAccessorComponentTypes");
const removeExtension = require("./removeExtension");

@@ -79,2 +80,8 @@ const Cartesian3 = Cesium.Cartesian3;

}
if (!options.keepLegacyExtensions) {
convertTechniquesToPbr(gltf);
convertMaterialsCommonToPbr(gltf);
}
return gltf;

@@ -540,3 +547,3 @@ }

const materialsCommon = extensions.KHR_materials_common;
if (defined(materialsCommon)) {
if (defined(materialsCommon) && defined(materialsCommon.values)) {
ForEach.materialValue(materialsCommon, function (value, name) {

@@ -706,3 +713,3 @@ if (typeof value === "string") {

} else if (!defined(knownSemantics[strippedSemantic])) {
newSemantic = "_" + semantic;
newSemantic = `_${semantic}`;
mappedSemantics[semantic] = newSemantic;

@@ -943,2 +950,16 @@ }

function validatePresentAccessorMinMax(gltf) {
ForEach.accessor(gltf, function (accessor) {
if (defined(accessor.min) || defined(accessor.max)) {
const minMax = findAccessorMinMax(gltf, accessor);
if (defined(accessor.min)) {
accessor.min = minMax.min;
}
if (defined(accessor.max)) {
accessor.max = minMax.max;
}
}
});
}
function glTF10to20(gltf) {

@@ -969,2 +990,5 @@ gltf.asset = defaultValue(gltf.asset, {});

requireAnimationAccessorMinMax(gltf);
// When an acccessor has a min- or max, then it is recomputed, to capture the actual
// value, and not use the (possibly imprecise) value from the input
validatePresentAccessorMinMax(gltf);
// buffer.type is unnecessary and should be removed

@@ -989,1 +1013,149 @@ removeBufferType(gltf);

}
// It's not possible to upgrade glTF 1.0 shaders to 2.0 PBR materials in a generic way,
// but we can look for certain uniform names that are commonly found in glTF 1.0 assets
// and create PBR materials out of those.
const baseColorTextureNames = ["u_tex", "u_diffuse", "u_emission"];
const baseColorFactorNames = ["u_diffuse"];
function initializePbrMaterial(material) {
material.pbrMetallicRoughness = defined(material.pbrMetallicRoughness)
? material.pbrMetallicRoughness
: {};
material.pbrMetallicRoughness.roughnessFactor = 1.0;
material.pbrMetallicRoughness.metallicFactor = 0.0;
}
function isTexture(value) {
return defined(value.index);
}
function isVec4(value) {
return Array.isArray(value) && value.length === 4;
}
function srgbToLinear(srgb) {
const linear = new Array(4);
linear[3] = srgb[3];
for (let i = 0; i < 3; i++) {
const c = srgb[i];
if (c <= 0.04045) {
// eslint-disable-next-line no-loss-of-precision
linear[i] = srgb[i] * 0.07739938080495356037151702786378;
} else {
linear[i] = Math.pow(
// eslint-disable-next-line no-loss-of-precision
(c + 0.055) * 0.94786729857819905213270142180095,
2.4
);
}
}
return linear;
}
function convertTechniquesToPbr(gltf) {
// Future work: convert other values like emissive, specular, etc. Only handling diffuse right now.
ForEach.material(gltf, function (material) {
ForEach.materialValue(material, function (value, name) {
if (baseColorTextureNames.indexOf(name) !== -1 && isTexture(value)) {
initializePbrMaterial(material);
material.pbrMetallicRoughness.baseColorTexture = value;
} else if (baseColorFactorNames.indexOf(name) !== -1 && isVec4(value)) {
initializePbrMaterial(material);
material.pbrMetallicRoughness.baseColorFactor = srgbToLinear(value);
}
});
});
removeExtension(gltf, "KHR_techniques_webgl");
removeExtension(gltf, "KHR_blend");
}
function convertMaterialsCommonToPbr(gltf) {
// Future work: convert KHR_materials_common lights to KHR_lights_punctual
ForEach.material(gltf, function (material) {
const materialsCommon = defaultValue(
material.extensions,
defaultValue.EMPTY_OBJECT
).KHR_materials_common;
if (defined(materialsCommon)) {
const technique = materialsCommon.technique;
if (technique === "CONSTANT") {
// Add the KHR_materials_unlit extension
addExtensionsUsed(gltf, "KHR_materials_unlit");
material.extensions = defined(material.extensions)
? material.extensions
: {};
material.extensions["KHR_materials_unlit"] = {};
}
const values = defined(materialsCommon.values)
? materialsCommon.values
: {};
const ambient = values.ambient;
const diffuse = values.diffuse;
const emission = values.emission;
const transparency = values.transparency;
// These actually exist on the extension object, not the values object despite what's shown in the spec
const doubleSided = materialsCommon.doubleSided;
const transparent = materialsCommon.transparent;
// Ignore specular and shininess for now because the conversion to PBR
// isn't straightforward and depends on the technique
initializePbrMaterial(material);
if (defined(ambient)) {
if (isVec4(ambient)) {
material.emissiveFactor = ambient.slice(0, 3);
} else if (isTexture(ambient)) {
material.emissiveTexture = ambient;
}
}
if (defined(diffuse)) {
if (isVec4(diffuse)) {
material.pbrMetallicRoughness.baseColorFactor = srgbToLinear(diffuse);
} else if (isTexture(diffuse)) {
material.pbrMetallicRoughness.baseColorTexture = diffuse;
}
}
if (defined(doubleSided)) {
material.doubleSided = doubleSided;
}
if (defined(emission)) {
if (isVec4(emission)) {
material.emissiveFactor = emission.slice(0, 3);
} else if (isTexture(emission)) {
material.emissiveTexture = emission;
}
}
if (defined(transparency)) {
if (defined(material.pbrMetallicRoughness.baseColorFactor)) {
material.pbrMetallicRoughness.baseColorFactor[3] *= transparency;
} else {
material.pbrMetallicRoughness.baseColorFactor = [
1,
1,
1,
transparency,
];
}
}
if (defined(transparent)) {
material.alphaMode = transparent ? "BLEND" : "OPAQUE";
}
}
});
removeExtension(gltf, "KHR_materials_common");
}

@@ -155,3 +155,3 @@ "use strict";

const mimeType = mime.getType(extension);
object.uri = "data:" + mimeType + ";base64," + source.toString("base64");
object.uri = `data:${mimeType};base64,${source.toString("base64")}`;
}

@@ -205,3 +205,3 @@

}
return "buffer" + index;
return `buffer${index}`;
} else if (extension === ".glsl") {

@@ -226,3 +226,3 @@ const programInfo = getProgram(gltf, index);

}
return "image" + index;
return `image${index}`;
}

@@ -243,3 +243,3 @@

while (defined(options.separateResources[relativePath])) {
relativePath = name + "_" + number + extension;
relativePath = `${name}_${number}${extension}`;
number++;

@@ -246,0 +246,0 @@ }

{
"name": "gltf-pipeline",
"version": "3.0.5",
"version": "4.0.1",
"description": "Content pipeline tools for optimizing glTF assets.",

@@ -26,3 +26,3 @@ "license": "Apache-2.0",

"engines": {
"node": ">=6.0.0"
"node": ">=16.0.0"
},

@@ -43,4 +43,5 @@ "dependencies": {

"eslint": "^8.0.1",
"eslint-config-cesium": "^8.0.1",
"eslint-config-cesium": "^9.0.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-node": "^11.1.0",
"gulp": "^4.0.2",

@@ -63,2 +64,3 @@ "husky": "^4.3.8",

"jsdoc": "jsdoc ./lib -R ./README.md -d doc",
"eslint-fix": "eslint \"./**/*.js\" --fix",
"eslint": "eslint \"./**/*.js\" --cache --quiet",

@@ -80,2 +82,2 @@ "eslint-watch": "gulp eslint-watch",

}
}
}

@@ -16,3 +16,3 @@ # glTF Pipeline

- Saving buffers/textures as embedded or separate files
- Converting glTF 1.0 models to glTF 2.0 (using the [KHR_techniques_webgl](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_techniques_webgl) and [KHR_blend](https://github.com/KhronosGroup/glTF/pull/1302) extensions)
- Converting glTF 1.0 models to glTF 2.0
- Applying [Draco](https://github.com/google/draco) mesh compression

@@ -131,2 +131,3 @@

| `--keepUnusedElements` | Keep unused materials, nodes and meshes. | No, default `false` |
| `--keepLegacyExtensions` | When false, materials with `KHR_techniques_webgl`, `KHR_blend`, or `KHR_materials_common` will be converted to PBR. | No, default `false` |
| `--draco.compressMeshes`, `-d` | Compress the meshes using Draco. Adds the KHR_draco_mesh_compression extension. | No, default `false` |

@@ -133,0 +134,0 @@ | `--draco.compressionLevel` | Draco compression level [0-10], most is 10, least is 0. A value of 0 will apply sequential encoding and preserve face order. | No, default `7` |

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc