Add back KHR_materials_common

This commit is contained in:
Sean Lilley 2017-05-04 15:39:01 -04:00
parent dc4ba7fc6a
commit 44e9d5fa3b
4 changed files with 123 additions and 33 deletions

View File

@ -48,8 +48,9 @@ Using obj2gltf as a command-line tool:
|`--inputUpAxis`|Up axis of the obj. Choices are 'X', 'Y', and 'Z'.|No, default `Y`| |`--inputUpAxis`|Up axis of the obj. Choices are 'X', 'Y', and 'Z'.|No, default `Y`|
|`--outputUpAxis`|Up axis of the converted glTF. Choices are 'X', 'Y', and 'Z'.|No, default `Y`| |`--outputUpAxis`|Up axis of the converted glTF. Choices are 'X', 'Y', and 'Z'.|No, default `Y`|
|`--packOcclusion`|Pack the occlusion texture in the red channel of metallic-roughness texture.|No, default `false`| |`--packOcclusion`|Pack the occlusion texture in the red channel of metallic-roughness texture.|No, default `false`|
|`--inputMetallicRoughness`|The values in the mtl file are already metallic-roughness PBR values and no conversion step should be applied. Metallic is stored in the Ks and map_Ks slots and roughness is stored in the Ns and map_Ns slots.|No, default `false`| |`--metallicRoughness`|The values in the mtl file are already metallic-roughness PBR values and no conversion step should be applied. Metallic is stored in the Ks and map_Ks slots and roughness is stored in the Ns and map_Ns slots.|No, default `false`|
|`--inputSpecularGlossiness`|The values in the mtl file are already specular-glossiness PBR values and no conversion step should be applied. Specular is stored in the Ks and map_Ks slots and glossiness is stored in the Ns and map_Ns slots. The glTF will be saved with the `KHR_materials_pbrSpecularGlossiness` extension.|No, default `false`| |`--specularGlossiness`|The values in the mtl file are already specular-glossiness PBR values and no conversion step should be applied. Specular is stored in the Ks and map_Ks slots and glossiness is stored in the Ns and map_Ns slots. The glTF will be saved with the `KHR_materials_pbrSpecularGlossiness` extension.|No, default `false`|
|`--materialsCommon`|The glTF will be saved with the KHR_materials_common extension.|No, default `false`|
## Build Instructions ## Build Instructions

View File

@ -108,15 +108,20 @@ var argv = yargs
type: 'boolean', type: 'boolean',
default: defaults.packOcclusion default: defaults.packOcclusion
}, },
inputMetallicRoughness : { metallicRoughness : {
describe: 'The values in the mtl file are already metallic-roughness PBR values and no conversion step should be applied. Metallic is stored in the Ks and map_Ks slots and roughness is stored in the Ns and map_Ns slots.', describe: 'The values in the mtl file are already metallic-roughness PBR values and no conversion step should be applied. Metallic is stored in the Ks and map_Ks slots and roughness is stored in the Ns and map_Ns slots.',
type: 'boolean', type: 'boolean',
default : defaults.metallicRoughness default: defaults.metallicRoughness
}, },
inputSpecularGlossiness : { specularGlossiness : {
describe: 'The values in the mtl file are already specular-glossiness PBR values and no conversion step should be applied. Specular is stored in the Ks and map_Ks slots and glossiness is stored in the Ns and map_Ns slots. The glTF will be saved with the KHR_materials_pbrSpecularGlossiness extension.', describe: 'The values in the mtl file are already specular-glossiness PBR values and no conversion step should be applied. Specular is stored in the Ks and map_Ks slots and glossiness is stored in the Ns and map_Ns slots. The glTF will be saved with the KHR_materials_pbrSpecularGlossiness extension.',
type: 'boolean', type: 'boolean',
default : defaults.specularGlossiness default: defaults.specularGlossiness
},
materialsCommon : {
describe: 'The glTF will be saved with the KHR_materials_common extension.',
type: 'boolean',
default: defaults.materialsCommon
} }
}).parse(args); }).parse(args);
@ -144,8 +149,8 @@ var options = {
inputUpAxis : argv.inputUpAxis, inputUpAxis : argv.inputUpAxis,
outputUpAxis : argv.outputUpAxis, outputUpAxis : argv.outputUpAxis,
packOcclusion : argv.packOcclusion, packOcclusion : argv.packOcclusion,
inputMetallicRoughness : argv.inputMetallicRoughness, metallicRoughness : argv.metallicRoughness,
inputSpecularGlossiness : argv.inputSpecularGlossiness specularGlossiness : argv.specularGlossiness
}; };
console.time('Total'); console.time('Total');

View File

@ -5,6 +5,7 @@ var PNG = require('pngjs').PNG;
var Material = require('./Material'); var Material = require('./Material');
var CesiumMath = Cesium.Math; var CesiumMath = Cesium.Math;
var defaultValue = Cesium.defaultValue;
var defined = Cesium.defined; var defined = Cesium.defined;
var WebGLConstants = Cesium.WebGLConstants; var WebGLConstants = Cesium.WebGLConstants;
@ -15,9 +16,10 @@ module.exports = createGltf;
* *
* @param {Object} objData Output of obj.js, containing an array of nodes containing geometry information, materials, and images. * @param {Object} objData Output of obj.js, containing an array of nodes containing geometry information, materials, and images.
* @param {Object} options An object with the following properties: * @param {Object} options An object with the following properties:
* @param {Boolean} [options.packOcclusion=false] Pack the occlusion texture in the red channel of metallic-roughness texture. * @param {Boolean} [options.packOcclusion] Pack the occlusion texture in the red channel of metallic-roughness texture.
* @param {Boolean} [options.inputMetallicRoughness=false] The values in the mtl file are already metallic-roughness PBR values and no conversion step should be applied. Metallic is stored in the Ks and map_Ks slots and roughness is stored in the Ns and map_Ns slots. * @param {Boolean} [options.metallicRoughness] The values in the mtl file are already metallic-roughness PBR values and no conversion step should be applied. Metallic is stored in the Ks and map_Ks slots and roughness is stored in the Ns and map_Ns slots.
* @param {Boolean} [options.inputSpecularGlossiness=false] The values in the mtl file are already specular-glossiness PBR values and no conversion step should be applied. Specular is stored in the Ks and map_Ks slots and glossiness is stored in the Ns and map_Ns slots. The glTF will be saved with the KHR_materials_pbrSpecularGlossiness extension. * @param {Boolean} [options.specularGlossiness] The values in the mtl file are already specular-glossiness PBR values and no conversion step should be applied. Specular is stored in the Ks and map_Ks slots and glossiness is stored in the Ns and map_Ns slots. The glTF will be saved with the KHR_materials_pbrSpecularGlossiness extension.
* @param {Boolean} [options.materialsCommon] The glTF will be saved with the KHR_materials_common extension.
* @param {Boolean} options.logger A callback function for handling logged messages. Defaults to console.log. * @param {Boolean} options.logger A callback function for handling logged messages. Defaults to console.log.
* @returns {Object} A glTF asset. * @returns {Object} A glTF asset.
* *
@ -33,6 +35,8 @@ function createGltf(objData, options) {
asset : {}, asset : {},
buffers : [], buffers : [],
bufferViews : [], bufferViews : [],
extensionsUsed : [],
extensionsRequired : [],
images : [], images : [],
materials : [], materials : [],
meshes : [], meshes : [],
@ -486,7 +490,10 @@ function createSpecularGlossinessMaterial(gltf, images, material, options) {
var doubleSided = transparent; var doubleSided = transparent;
var alphaMode = transparent ? 'BLEND' : 'OPAQUE'; var alphaMode = transparent ? 'BLEND' : 'OPAQUE';
var gltfMaterial = { gltf.extensionsUsed.push('KHR_materials_pbrSpecularGlossiness');
gltf.extensionsRequired.push('KHR_materials_pbrSpecularGlossiness');
return {
name : materialName, name : materialName,
extensions : { extensions : {
KHR_materials_pbrSpecularGlossiness: { KHR_materials_pbrSpecularGlossiness: {
@ -504,8 +511,6 @@ function createSpecularGlossinessMaterial(gltf, images, material, options) {
alphaMode : alphaMode, alphaMode : alphaMode,
doubleSided : doubleSided doubleSided : doubleSided
}; };
return gltfMaterial;
} }
function createMetallicRoughnessMaterial(gltf, images, material, options) { function createMetallicRoughnessMaterial(gltf, images, material, options) {
@ -558,7 +563,7 @@ function createMetallicRoughnessMaterial(gltf, images, material, options) {
var doubleSided = transparent; var doubleSided = transparent;
var alphaMode = transparent ? 'BLEND' : 'OPAQUE'; var alphaMode = transparent ? 'BLEND' : 'OPAQUE';
var gltfMaterial = { return {
name : materialName, name : materialName,
pbrMetallicRoughness : { pbrMetallicRoughness : {
baseColorTexture : baseColorTexture, baseColorTexture : baseColorTexture,
@ -574,14 +579,13 @@ function createMetallicRoughnessMaterial(gltf, images, material, options) {
alphaMode : alphaMode, alphaMode : alphaMode,
doubleSided : doubleSided doubleSided : doubleSided
}; };
return gltfMaterial;
} }
function convertTraditionalToMetallicRoughness(material) { function convertTraditionalToMetallicRoughness(material) {
// Translate the blinn-phong model to the pbr metallic-roughness model // Translate the blinn-phong model to the pbr metallic-roughness model
// Roughness factor is a combination of specular intensity and shininess // Roughness factor is a combination of specular intensity and shininess
// Metallic factor is 0.0 // Metallic factor is 0.0
// This does not convert textures
var specularIntensity = material.specularColor[0]; var specularIntensity = material.specularColor[0];
var specularShininess = material.specularShininess; var specularShininess = material.specularShininess;
@ -602,12 +606,83 @@ function convertTraditionalToMetallicRoughness(material) {
material.specularShiness = roughnessFactor; material.specularShiness = roughnessFactor;
} }
function addMaterial(gltf, images, material, options) { function createMaterialsCommonMaterial(gltf, images, material, hasNormals, options) {
var materialName = material.name;
var ambientImage = getImage(images, material.ambientTexture);
var diffuseImage = getImage(images, material.diffuseTexture);
var emissiveImage = getImage(images, material.emissiveTexture);
var specularImage = getImage(images, material.specularTexture);
var ambient = defaultValue(getTexture(gltf, ambientImage), material.ambientColor);
var diffuse = defaultValue(getTexture(gltf, diffuseImage), material.diffuseColor);
var emission = defaultValue(getTexture(gltf, emissiveImage), material.emissiveColor);
var specular = defaultValue(getTexture(gltf, specularImage), material.specularColor);
var alpha = material.alpha;
var shininess = material.specularShininess;
var hasSpecular = (shininess > 0.0) && (specular[0] > 0.0 || specular[1] > 0.0 || specular[2] > 0.0);
var transparent;
var transparency = 1.0;
if (defined(diffuseImage)) {
transparency = alpha;
transparent = diffuseImage.transparent || (transparency < 1.0);
} else {
diffuse[3] = alpha;
transparent = alpha < 1.0;
}
if (!defined(ambientImage)) {
// If ambient color is [1, 1, 1] assume it is a multiplier and instead change to [0, 0, 0]
if (ambient[0] === 1.0 && ambient[1] === 1.0 && ambient[2] === 1.0) {
ambient = [0.0, 0.0, 0.0, 1.0];
}
}
var doubleSided = transparent;
if (!hasNormals) {
// Constant technique only factors in ambient and emission sources - set emission to diffuse
emission = diffuse;
diffuse = [0, 0, 0, 1];
}
var technique = hasNormals ? (hasSpecular ? 'PHONG' : 'LAMBERT') : 'CONSTANT';
gltf.extensionsUsed.push('KHR_materials_common');
gltf.extensionsRequired.push('KHR_materials_common');
return {
name : materialName,
extensions : {
KHR_materials_common : {
technique : technique,
transparent : transparent,
doubleSided : doubleSided,
values : {
ambient : ambient,
diffuse : diffuse,
emission : emission,
specular : specular,
shininess : shininess,
transparency : transparency,
transparent : transparent,
doubleSided : doubleSided
}
}
}
};
}
function addMaterial(gltf, images, material, hasNormals, options) {
var gltfMaterial; var gltfMaterial;
if (options.inputSpecularGlossiness) { if (options.specularGlossiness) {
gltfMaterial = createSpecularGlossinessMaterial(gltf, images, material, options); gltfMaterial = createSpecularGlossinessMaterial(gltf, images, material, options);
} else if (options.inputMetallicRoughness) { } else if (options.metallicRoughness) {
gltfMaterial = createMetallicRoughnessMaterial(gltf, images, material, options); gltfMaterial = createMetallicRoughnessMaterial(gltf, images, material, options);
} else if (options.materialsCommon) {
gltfMaterial = createMaterialsCommonMaterial(gltf, images, material, hasNormals, options);
} else { } else {
convertTraditionalToMetallicRoughness(material); convertTraditionalToMetallicRoughness(material);
gltfMaterial = createMetallicRoughnessMaterial(gltf, images, material, options); gltfMaterial = createMetallicRoughnessMaterial(gltf, images, material, options);
@ -629,7 +704,7 @@ function getMaterialIndex(gltf, materialName) {
return undefined; return undefined;
} }
function getMaterial(gltf, materials, images, materialName, options) { function getMaterial(gltf, materials, images, materialName, hasNormals, options) {
if (!defined(materialName)) { if (!defined(materialName)) {
// Create a default material if the primitive does not specify one // Create a default material if the primitive does not specify one
materialName = 'default'; materialName = 'default';
@ -651,7 +726,7 @@ function getMaterial(gltf, materials, images, materialName, options) {
var materialIndex = getMaterialIndex(gltf, materialName); var materialIndex = getMaterialIndex(gltf, materialName);
if (!defined(materialIndex)) { if (!defined(materialIndex)) {
materialIndex = addMaterial(gltf, images, material, options); materialIndex = addMaterial(gltf, images, material, hasNormals, options);
} }
return materialIndex; return materialIndex;
@ -750,7 +825,7 @@ function addMesh(gltf, materials, images, bufferState, uint32Indices, mesh, opti
var indexAccessorIndex = addIndexArray(gltf, bufferState, primitive.indices, uint32Indices); var indexAccessorIndex = addIndexArray(gltf, bufferState, primitive.indices, uint32Indices);
primitive.indices = undefined; // Unload resources primitive.indices = undefined; // Unload resources
var materialIndex = getMaterial(gltf, materials, images, primitive.material, options); var materialIndex = getMaterial(gltf, materials, images, primitive.material, hasNormals, options);
gltfPrimitives.push({ gltfPrimitives.push({
attributes : attributes, attributes : attributes,

View File

@ -40,8 +40,9 @@ module.exports = obj2gltf;
* @param {String} [options.inputUpAxis='Y'] Up axis of the obj. Choices are 'X', 'Y', and 'Z'. * @param {String} [options.inputUpAxis='Y'] Up axis of the obj. Choices are 'X', 'Y', and 'Z'.
* @param {String} [options.outputUpAxis='Y'] Up axis of the converted glTF. Choices are 'X', 'Y', and 'Z'. * @param {String} [options.outputUpAxis='Y'] Up axis of the converted glTF. Choices are 'X', 'Y', and 'Z'.
* @param {Boolean} [options.packOcclusion=false] Pack the occlusion texture in the red channel of metallic-roughness texture. * @param {Boolean} [options.packOcclusion=false] Pack the occlusion texture in the red channel of metallic-roughness texture.
* @param {Boolean} [options.inputMetallicRoughness=false] The values in the mtl file are already metallic-roughness PBR values and no conversion step should be applied. Metallic is stored in the Ks and map_Ks slots and roughness is stored in the Ns and map_Ns slots. * @param {Boolean} [options.metallicRoughness=false] The values in the mtl file are already metallic-roughness PBR values and no conversion step should be applied. Metallic is stored in the Ks and map_Ks slots and roughness is stored in the Ns and map_Ns slots.
* @param {Boolean} [options.inputSpecularGlossiness=false] The values in the mtl file are already specular-glossiness PBR values and no conversion step should be applied. Specular is stored in the Ks and map_Ks slots and glossiness is stored in the Ns and map_Ns slots. The glTF will be saved with the KHR_materials_pbrSpecularGlossiness extension. * @param {Boolean} [options.specularGlossiness=false] The values in the mtl file are already specular-glossiness PBR values and no conversion step should be applied. Specular is stored in the Ks and map_Ks slots and glossiness is stored in the Ns and map_Ns slots. The glTF will be saved with the KHR_materials_pbrSpecularGlossiness extension.
* @param {Boolean} [options.materialsCommon=false] The glTF will be saved with the KHR_materials_common extension.
* @param {Logger} [options.logger] A callback function for handling logged messages. Defaults to console.log. * @param {Logger} [options.logger] A callback function for handling logged messages. Defaults to console.log.
*/ */
function obj2gltf(objPath, gltfPath, options) { function obj2gltf(objPath, gltfPath, options) {
@ -63,8 +64,9 @@ function obj2gltf(objPath, gltfPath, options) {
var inputUpAxis = defaultValue(options.inputUpAxis, defaults.inputUpAxis); var inputUpAxis = defaultValue(options.inputUpAxis, defaults.inputUpAxis);
var outputUpAxis = defaultValue(options.outputUpAxis, defaults.outputUpAxis); var outputUpAxis = defaultValue(options.outputUpAxis, defaults.outputUpAxis);
var packOcclusion = defaultValue(options.packOcclusion, defaults.packOcclusion); var packOcclusion = defaultValue(options.packOcclusion, defaults.packOcclusion);
var inputMetallicRoughness = defaultValue(options.inputMetallicRoughness, defaults.inputMetallicRoughness); var metallicRoughness = defaultValue(options.metallicRoughness, defaults.metallicRoughness);
var inputSpecularGlossiness = defaultValue(options.inputSpecularGlossiness, defaults.inputSpecularGlossiness); var specularGlossiness = defaultValue(options.specularGlossiness, defaults.specularGlossiness);
var materialsCommon = defaultValue(options.materialsCommon, defaults.materialsCommon);
var logger = defaultValue(options.logger, defaults.logger); var logger = defaultValue(options.logger, defaults.logger);
options.separate = separate; options.separate = separate;
@ -74,8 +76,9 @@ function obj2gltf(objPath, gltfPath, options) {
options.inputUpAxis = inputUpAxis; options.inputUpAxis = inputUpAxis;
options.outputUpAxis = outputUpAxis; options.outputUpAxis = outputUpAxis;
options.packOcclusion = packOcclusion; options.packOcclusion = packOcclusion;
options.inputMetallicRoughness = inputMetallicRoughness; options.metallicRoughness = metallicRoughness;
options.inputSpecularGlossiness = inputSpecularGlossiness; options.specularGlossiness = specularGlossiness;
options.materialsCommon = materialsCommon;
options.logger = logger; options.logger = logger;
if (!defined(objPath)) { if (!defined(objPath)) {
@ -96,8 +99,8 @@ function obj2gltf(objPath, gltfPath, options) {
return Promise.reject(new RuntimeError('--bypassPipeline does not convert to binary glTF')); return Promise.reject(new RuntimeError('--bypassPipeline does not convert to binary glTF'));
} }
if (inputMetallicRoughness && inputSpecularGlossiness) { if (metallicRoughness + specularGlossiness + materialsCommon > 1) {
throw new DeveloperError('--inputMetallicRoughness and --inputSpecularGlossiness cannot both be set.'); throw new DeveloperError('Only one material type may be set from [--metallicRoughness, --specularGlossiness, --materialsCommon].');
} }
gltfPath = path.join(path.dirname(gltfPath), modelName + extension); gltfPath = path.join(path.dirname(gltfPath), modelName + extension);
@ -243,13 +246,19 @@ obj2gltf.defaults = {
* @type Boolean * @type Boolean
* @default false * @default false
*/ */
inputMetallicRoughness: false, metallicRoughness: false,
/** /**
* The values in the mtl file are already specular-glossiness PBR values and no conversion step should be applied. Specular is stored in the Ks and map_Ks slots and glossiness is stored in the Ns and map_Ns slots. The glTF will be saved with the KHR_materials_pbrSpecularGlossiness extension. * The values in the mtl file are already specular-glossiness PBR values and no conversion step should be applied. Specular is stored in the Ks and map_Ks slots and glossiness is stored in the Ns and map_Ns slots. The glTF will be saved with the KHR_materials_pbrSpecularGlossiness extension.
* @type Boolean * @type Boolean
* @default false * @default false
*/ */
inputSpecularGlossiness: false, specularGlossiness: false,
/**
* The values in the mtl file are already specular-glossiness PBR values and no conversion step should be applied. Specular is stored in the Ks and map_Ks slots and glossiness is stored in the Ns and map_Ns slots. The glTF will be saved with the KHR_materials_pbrSpecularGlossiness extension.
* @type Boolean
* @default false
*/
materialsCommon: false,
/** /**
* @private * @private