From 3da691df6289ec23a2a24acbf83e00a3dd42b71e Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Fri, 28 Jul 2017 16:56:28 -0400 Subject: [PATCH] Cleanup overriding images --- bin/obj2gltf.js | 26 ++++++++++- lib/Image.js | 18 ++++++++ lib/createGltf.js | 86 +++++++++++++++++------------------ lib/loadImage.js | 65 +++++++++++++-------------- lib/loadMtl.js | 2 +- lib/obj2gltf.js | 61 ++++++++++++++++--------- specs/lib/createGltfSpec.js | 2 +- specs/lib/loadImageSpec.js | 90 ++++++++++++++++++------------------- specs/lib/obj2gltfSpec.js | 24 ++++++++++ 9 files changed, 227 insertions(+), 147 deletions(-) create mode 100644 lib/Image.js diff --git a/bin/obj2gltf.js b/bin/obj2gltf.js index dab8dc8..fdd2704 100644 --- a/bin/obj2gltf.js +++ b/bin/obj2gltf.js @@ -131,10 +131,34 @@ if (!defined(gltfPath)) { gltfPath = path.join(path.dirname(objPath), modelName + extension); } +var overridingImages = { + metallicRoughnessOcclusionTexture : argv.metallicRoughnessOcclusionTexture, + specularGlossinessTexture : argv.specularGlossinessTexture, + occlusionTexture : argv.occlusionTexture, + normalTexture : argv.normalTexture, + baseColorTexture : argv.baseColorTexture, + emissiveTexture : argv.emissiveTexture +}; + +var options = { + binary : argv.binary, + separate : argv.separate, + separateTextures : argv.separateTextures, + checkTransparency : argv.checkTransparency, + secure : argv.secure, + inputUpAxis : argv.inputUpAxis, + outputUpAxis : argv.outputUpAxis, + packOcclusion : argv.packOcclusion, + metallicRoughness : argv.metallicRoughness, + specularGlossiness : argv.specularGlossiness, + materialsCommon : argv.materialsCommon, + overridingImages : overridingImages +}; + console.time('Total'); try { - obj2gltf(objPath, gltfPath, argv) + obj2gltf(objPath, gltfPath, options) .then(function() { console.timeEnd('Total'); }) diff --git a/lib/Image.js b/lib/Image.js new file mode 100644 index 0000000..afcc4da --- /dev/null +++ b/lib/Image.js @@ -0,0 +1,18 @@ +'use strict'; + +module.exports = Image; + +/** + * Stores image data and properties. + * + * @private + */ +function Image() { + this.transparent = false; + this.source = undefined; + this.extension = undefined; + this.path = undefined; + this.decoded = undefined; + this.width = undefined; + this.height = undefined; +} diff --git a/lib/createGltf.js b/lib/createGltf.js index e377156..01c6093 100644 --- a/lib/createGltf.js +++ b/lib/createGltf.js @@ -2,6 +2,7 @@ var Cesium = require('cesium'); var path = require('path'); var getBufferPadded = require('./getBufferPadded'); +var Image = require('./Image'); var Material = require('./Material'); var CesiumMath = Cesium.Math; @@ -20,13 +21,13 @@ module.exports = createGltf; * @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.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 {Object[]} options.overridingImages An array of images that override images in the .mtl file. - * @param {String} [options.metallicRoughnessOcclusionTexture] Path to the metallic-roughness-occlusion texture used by the model, where occlusion is stored in the red channel, roughness is stored in the green channel, and metallic is stored in the blue channel. This may be used instead of setting texture paths in the .mtl file, and is intended for models that use one material. The model will be saved with a pbrMetallicRoughness material. - * @param {String} [options.specularGlossinessTexture] Path to the specular-glossiness texture used by the model, where specular color is stored in the red, green, and blue channels and specular glossiness is stored in the alpha channel. This may be used instead of setting texture paths in the .mtl file, and is intended for models that use one material. The model will be saved with a material using the KHR_materials_pbrSpecularGlossiness extension. - * @param {String} [options.occlusionTexture] Path to the occlusion texture used by the model. This may be used instead of setting texture paths in the .mtl file, and is intended for models that use one material. Ignored if metallicRoughnessOcclusionTexture is also set. - * @param {String} [options.normalTexture] Path to the normal texture used by the model. This may be used instead of setting texture paths in the .mtl file, and is intended for models that use one material. - * @param {String} [options.baseColorTexture] Path to the baseColor/diffuse texture used by the model. This may be used instead of setting texture paths in the .mtl file, and is intended for models that use one material. - * @param {String} [options.emissiveTexture] Path to the emissive texture used by the model. This may be used instead of setting texture paths in the .mtl file, and is intended for models that use one material. + * @param {Object} [options.overridingImages] An object containing image paths that override material values defined in the .mtl file. This is often convenient in workflows where the .mtl does not exist or is not set up to use PBR materials. Intended for models with a single material. + * @param {String} [options.overridingImages.metallicRoughnessOcclusionTexture] Path to the metallic-roughness-occlusion texture, where occlusion is stored in the red channel, roughness is stored in the green channel, and metallic is stored in the blue channel. The model will be saved with a pbrMetallicRoughness material. + * @param {String} [options.overridingImages.specularGlossinessTexture] Path to the specular-glossiness texture, where specular color is stored in the red, green, and blue channels and specular glossiness is stored in the alpha channel. The model will be saved with a material using the KHR_materials_pbrSpecularGlossiness extension. + * @param {String} [options.overridingImages.occlusionTexture] Path to the occlusion texture. Ignored if metallicRoughnessOcclusionTexture is also set. + * @param {String} [options.overridingImages.normalTexture] Path to the normal texture. + * @param {String} [options.overridingImages.baseColorTexture] Path to the baseColor/diffuse texture. + * @param {String} [options.overridingImages.emissiveTexture] Path to the emissive texture. * @param {Boolean} options.logger A callback function for handling logged messages. Defaults to console.log. * @returns {Object} A glTF asset. * @@ -158,9 +159,10 @@ function addBuffers(gltf, bufferState) { }); } -function getImage(images, imagePath, overrideImagePath, options) { - images = options.overridingImages.concat(images); - imagePath = defaultValue(overrideImagePath, imagePath); +function getImage(images, imagePath, overridingImage) { + if (defined(overridingImage)) { + return overridingImage; + } var imagesLength = images.length; for (var i = 0; i < imagesLength; ++i) { var image = images[i]; @@ -383,15 +385,12 @@ function createMetallicRoughnessTexture(gltf, metallicImage, roughnessImage, occ } var imageName = imageNames.join('_'); - var image = { - transparent : false, - source : undefined, - extension : '.png', - path : imageName, - decoded : pixels, - width : width, - height : height - }; + var image = new Image(); + image.extension = '.png'; + image.path = imageName; + image.decoded = pixels; + image.width = width; + image.height = height; return getTexture(gltf, image); } @@ -448,15 +447,12 @@ function createSpecularGlossinessTexture(gltf, specularImage, glossinessImage, o } var imageName = imageNames.join('_'); - var image = { - transparent : true, - source : undefined, - extension : '.png', - path : imageName, - decoded : pixels, - width : width, - height : height - }; + var image = new Image(); + image.extension = '.png'; + image.path = imageName; + image.decoded = pixels; + image.width = width; + image.height = height; return getTexture(gltf, image); } @@ -465,12 +461,13 @@ function createSpecularGlossinessMaterial(gltf, images, material, options) { var materialName = material.name; // The texture paths supplied in the .mtl may be overriden by the texture paths supplied in options - var emissiveImage = getImage(images, material.emissiveTexture, options.emissiveTexture, options); - var normalImage = getImage(images, material.normalTexture, options.normalTexture, options); - var occlusionImage = getImage(images, material.ambientTexture, options.occlusionTexture, options); - var diffuseImage = getImage(images, material.diffuseTexture, options.baseColorTexture, options); - var specularImage = getImage(images, material.specularTexture, options.specularGlossinessTexture, options); - var glossinessImage = getImage(images, material.specularShininessTexture, options.specularGlossinessTexture, options); + var overridingImages = options.overridingImages; + var emissiveImage = getImage(images, material.emissiveTexture, overridingImages.emissiveTexture, options); + var normalImage = getImage(images, material.normalTexture, overridingImages.normalTexture, options); + var occlusionImage = getImage(images, material.ambientTexture, overridingImages.occlusionTexture, options); + var diffuseImage = getImage(images, material.diffuseTexture, overridingImages.baseColorTexture, options); + var specularImage = getImage(images, material.specularTexture, overridingImages.specularGlossinessTexture, options); + var glossinessImage = getImage(images, material.specularShininessTexture, overridingImages.specularGlossinessTexture, options); var emissiveTexture = getTexture(gltf, emissiveImage); var normalTexture = getTexture(gltf, normalImage); @@ -478,7 +475,7 @@ function createSpecularGlossinessMaterial(gltf, images, material, options) { var diffuseTexture = getTexture(gltf, diffuseImage); var specularGlossinessTexture; - if (defined(options.specularGlossinessTexture)) { + if (defined(overridingImages.specularGlossinessTexture)) { specularGlossinessTexture = getTexture(gltf, specularImage); } else { specularGlossinessTexture = createSpecularGlossinessTexture(gltf, specularImage, glossinessImage, options); @@ -542,26 +539,27 @@ function createSpecularGlossinessMaterial(gltf, images, material, options) { function createMetallicRoughnessMaterial(gltf, images, material, options) { var materialName = material.name; - // The texture paths supplied in the .mtl may be overriden by the texture paths supplied in options - var emissiveImage = getImage(images, material.emissiveTexture, options.emissiveTexture, options); - var normalImage = getImage(images, material.normalTexture, options.normalTexture, options); - var occlusionImage = getImage(images, material.ambientTexture, options.metallicRoughnessOcclusionTexture, options); - var baseColorImage = getImage(images, material.diffuseTexture, options.baseColorTexture, options); - var metallicImage = getImage(images, material.specularTexture, options.metallicRoughnessOcclusionTexture, options); - var roughnessImage = getImage(images, material.specularShininessTexture, options.metallicRoughnessOcclusionTexture, options); + // The texture paths supplied in the .mtl may be over var overridingImages = options.overridingImages; + var overridingImages = options.overridingImages; + var emissiveImage = getImage(images, material.emissiveTexture, overridingImages.emissiveTexture); + var normalImage = getImage(images, material.normalTexture, overridingImages.normalTexture); + var occlusionImage = getImage(images, material.ambientTexture, overridingImages.metallicRoughnessOcclusionTexture); + var baseColorImage = getImage(images, material.diffuseTexture, overridingImages.baseColorTexture); + var metallicImage = getImage(images, material.specularTexture, overridingImages.metallicRoughnessOcclusionTexture); + var roughnessImage = getImage(images, material.specularShininessTexture, overridingImages.metallicRoughnessOcclusionTexture); var emissiveTexture = getTexture(gltf, emissiveImage); var normalTexture = getTexture(gltf, normalImage); var baseColorTexture = getTexture(gltf, baseColorImage); var metallicRoughnessTexture; - if (defined(options.metallicRoughnessOcclusionTexture)) { + if (defined(overridingImages.metallicRoughnessOcclusionTexture)) { metallicRoughnessTexture = getTexture(gltf, metallicImage); } else { metallicRoughnessTexture = createMetallicRoughnessTexture(gltf, metallicImage, roughnessImage, occlusionImage, options); } - var packOcclusion = (defined(occlusionImage) && options.packOcclusion) || defined(options.metallicRoughnessOcclusionTexture); + var packOcclusion = (defined(occlusionImage) && options.packOcclusion) || defined(overridingImages.metallicRoughnessOcclusionTexture); var occlusionTexture = packOcclusion ? metallicRoughnessTexture : getTexture(gltf, occlusionImage); var emissiveFactor = getEmissiveFactor(material); diff --git a/lib/loadImage.js b/lib/loadImage.js index 7ed720d..73dfd99 100644 --- a/lib/loadImage.js +++ b/lib/loadImage.js @@ -5,6 +5,7 @@ var jpeg = require('jpeg-js'); var path = require('path'); var PNG = require('pngjs').PNG; var Promise = require('bluebird'); +var Image = require('./Image'); var defaultValue = Cesium.defaultValue; var defined = Cesium.defined; @@ -12,13 +13,13 @@ var defined = Cesium.defined; module.exports = loadImage; /** - * Load an image file and get information about it. + * Load an image file. * * @param {String} imagePath Path to the image file. * @param {Object} options An object with the following properties: * @param {Boolean} [options.checkTransparency=false] Do a more exhaustive check for texture transparency by looking at the alpha channel of each pixel. * @param {Boolean} [options.decode=false] Decode image. - * @returns {Promise} A promise resolving to the image information, or undefined if the file doesn't exist. + * @returns {Promise} A promise resolving to an Image object. * * @private */ @@ -30,30 +31,29 @@ function loadImage(imagePath, options) { return fsExtra.readFile(imagePath) .then(function(data) { var extension = path.extname(imagePath).toLowerCase(); + var image = new Image(); + image.source = data; + image.extension = extension; + image.path = imagePath; - var info = { - transparent : false, - source : data, - extension : extension, - path : imagePath, - decoded : undefined, - width : undefined, - height : undefined - }; - + var decodePromise; if (extension === '.png') { - return getPngInfo(data, info, options); + decodePromise = decodePng(image, options); } else if (extension === '.jpg' || extension === '.jpeg') { - return getJpegInfo(data, info, options); + decodePromise = decodeJpeg(image, options); } - return info; + if (defined(decodePromise)) { + return decodePromise.thenReturn(image); + } + + return image; }); } -function hasTransparency(info) { - var pixels = info.decoded; - var pixelsLength = info.width * info.height; +function hasTransparency(image) { + var pixels = image.decoded; + var pixelsLength = image.width * image.height; for (var i = 0; i < pixelsLength; ++i) { if (pixels[i * 4 + 3] < 255) { return true; @@ -89,35 +89,34 @@ function parsePng(data) { }); } -function getPngInfo(data, info, options) { +function decodePng(image, options) { // Color type is encoded in the 25th bit of the png - var colorType = data[25]; + var source = image.source; + var colorType = source[25]; var channels = getChannels(colorType); var checkTransparency = (channels === 4 && options.checkTransparency); var decode = options.decode || checkTransparency; if (decode) { - return parsePng(data) + return parsePng(source) .then(function(decodedResults) { - info.decoded = decodedResults.data; - info.width = decodedResults.width; - info.height = decodedResults.height; + image.decoded = decodedResults.data; + image.width = decodedResults.width; + image.height = decodedResults.height; if (checkTransparency) { - info.transparent = hasTransparency(info); + image.transparent = hasTransparency(image); } - return info; }); } - return info; } -function getJpegInfo(data, info, options) { +function decodeJpeg(image, options) { if (options.decode) { - var decodedResults = jpeg.decode(data); - info.decoded = decodedResults.data; - info.width = decodedResults.width; - info.height = decodedResults.height; + var source = image.source; + var decodedResults = jpeg.decode(source); + image.decoded = decodedResults.data; + image.width = decodedResults.width; + image.height = decodedResults.height; } - return info; } diff --git a/lib/loadMtl.js b/lib/loadMtl.js index 2cb4d59..c72eb56 100644 --- a/lib/loadMtl.js +++ b/lib/loadMtl.js @@ -11,7 +11,7 @@ module.exports = loadMtl; * @param {String} mtlPath Path to the mtl file. * @param {Object} options An object with the following properties: * @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. - * @returns {Promise} A promise resolving to the materials. + * @returns {Promise} A promise resolving to an array of materials. * * @private */ diff --git a/lib/obj2gltf.js b/lib/obj2gltf.js index 740317b..3d032a5 100644 --- a/lib/obj2gltf.js +++ b/lib/obj2gltf.js @@ -32,12 +32,13 @@ module.exports = obj2gltf; * @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.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 {String} [options.metallicRoughnessOcclusionTexture] Path to the metallic-roughness-occlusion texture used by the model, where occlusion is stored in the red channel, roughness is stored in the green channel, and metallic is stored in the blue channel. This may be used instead of setting texture paths in the .mtl file, and is intended for models that use one material. The model will be saved with a pbrMetallicRoughness material. - * @param {String} [options.specularGlossinessTexture] Path to the specular-glossiness texture used by the model, where specular color is stored in the red, green, and blue channels and specular glossiness is stored in the alpha channel. This may be used instead of setting texture paths in the .mtl file, and is intended for models that use one material. The model will be saved with a material using the KHR_materials_pbrSpecularGlossiness extension. - * @param {String} [options.occlusionTexture] Path to the occlusion texture used by the model. This may be used instead of setting texture paths in the .mtl file, and is intended for models that use one material. Ignored if metallicRoughnessOcclusionTexture is also set. - * @param {String} [options.normalTexture] Path to the normal texture used by the model. This may be used instead of setting texture paths in the .mtl file, and is intended for models that use one material. - * @param {String} [options.baseColorTexture] Path to the baseColor/diffuse texture used by the model. This may be used instead of setting texture paths in the .mtl file, and is intended for models that use one material. - * @param {String} [options.emissiveTexture] Path to the emissive texture used by the model. This may be used instead of setting texture paths in the .mtl file, and is intended for models that use one material. + * @param {Object} [options.overridingImages] An object containing image paths that override material values defined in the .mtl file. This is often convenient in workflows where the .mtl does not exist or is not set up to use PBR materials. Intended for models with a single material. + * @param {String} [options.overridingImages.metallicRoughnessOcclusionTexture] Path to the metallic-roughness-occlusion texture, where occlusion is stored in the red channel, roughness is stored in the green channel, and metallic is stored in the blue channel. The model will be saved with a pbrMetallicRoughness material. + * @param {String} [options.overridingImages.specularGlossinessTexture] Path to the specular-glossiness texture, where specular color is stored in the red, green, and blue channels and specular glossiness is stored in the alpha channel. The model will be saved with a material using the KHR_materials_pbrSpecularGlossiness extension. + * @param {String} [options.overridingImages.occlusionTexture] Path to the occlusion texture. Ignored if metallicRoughnessOcclusionTexture is also set. + * @param {String} [options.overridingImages.normalTexture] Path to the normal texture. + * @param {String} [options.overridingImages.baseColorTexture] Path to the baseColor/diffuse texture. + * @param {String} [options.overridingImages.emissiveTexture] Path to the emissive texture. * @param {Logger} [options.logger] A callback function for handling logged messages. Defaults to console.log. * @return {Promise} A promise that resolves when the glTF file is saved. @@ -57,6 +58,7 @@ function obj2gltf(objPath, gltfPath, options) { var metallicRoughness = defaultValue(options.metallicRoughness, defaults.metallicRoughness); var specularGlossiness = defaultValue(options.specularGlossiness, defaults.specularGlossiness); var materialsCommon = defaultValue(options.materialsCommon, defaults.materialsCommon); + var overridingImages = defaultValue(options.overridingImages, defaultValue.EMPTY_OBJECT); var logger = defaultValue(options.logger, defaults.logger); options.separate = separate; @@ -69,6 +71,7 @@ function obj2gltf(objPath, gltfPath, options) { options.metallicRoughness = metallicRoughness; options.specularGlossiness = specularGlossiness; options.materialsCommon = materialsCommon; + options.overridingImages = overridingImages; options.logger = logger; if (!defined(objPath)) { @@ -83,17 +86,17 @@ function obj2gltf(objPath, gltfPath, options) { throw new DeveloperError('Only one material type may be set from [--metallicRoughness, --specularGlossiness, --materialsCommon].'); } - if (defined(options.metallicRoughnessOcclusionTexture) && defined(options.specularGlossinessTexture)) { - throw new DeveloperError('options.metallicRoughnessOcclusionTexture and options.specularGlossinessTexture cannot both be defined.'); + if (defined(overridingImages.metallicRoughnessOcclusionTexture) && defined(overridingImages.specularGlossinessTexture)) { + throw new DeveloperError('options.overridingImages.metallicRoughnessOcclusionTexture and options.overridingImages.specularGlossinessTexture cannot both be defined.'); } - if (defined(options.metallicRoughnessOcclusionTexture)) { + if (defined(overridingImages.metallicRoughnessOcclusionTexture)) { options.metallicRoughness = true; options.specularGlossiness = false; options.materialsCommon = false; } - if (defined(options.specularGlossinessTexture)) { + if (defined(overridingImages.specularGlossinessTexture)) { options.metallicRoughness = false; options.specularGlossiness = true; options.materialsCommon = false; @@ -131,18 +134,32 @@ function obj2gltf(objPath, gltfPath, options) { } function loadOverridingImages(options) { - // The texture paths supplied in the .mtl may be overriden by the texture path supplied in options - var checkTransparencyOptions = { - checkTransparency : options.checkTransparency - }; - var imagePaths = [options.metallicRoughnessOcclusionTexture, options.specularGlossinessTexture, options.occlusionTexture, options.normalTexture, options.baseColorTexture, options.emissiveTexture]; - imagePaths = imagePaths.filter(function(imagePath) {return defined(imagePath);}); - return Promise.map(imagePaths, function(imagePath) { - var imageOptions = (imagePath === options.baseColorTexture) ? checkTransparencyOptions : undefined; - return loadImage(imagePath, imageOptions); - }).then(function(images) { - options.overridingImages = images; - }); + var overridingImages = options.overridingImages; + var promises = []; + for (var imageName in overridingImages) { + if (overridingImages.hasOwnProperty(imageName)) { + promises.push(loadOverridingImage(imageName, overridingImages, options)); + } + } + return Promise.all(promises); +} + +function loadOverridingImage(imageName, overridingImages, options) { + var imagePath = overridingImages[imageName]; + var imageOptions; + if (imageName === 'baseColorTexture') { + imageOptions = { + checkTransparency : options.checkTransparency + }; + } + return loadImage(imagePath, imageOptions) + .then(function(image) { + overridingImages[imageName] = image; + }) + .catch(function() { + delete overridingImages[imageName]; + options.logger('Could not read image file at ' + imagePath + '. This image will be ignored.'); + }); } /** diff --git a/specs/lib/createGltfSpec.js b/specs/lib/createGltfSpec.js index 3fe2974..4881229 100644 --- a/specs/lib/createGltfSpec.js +++ b/specs/lib/createGltfSpec.js @@ -21,7 +21,7 @@ var metallicTextureUrl = 'specs/data/box-complex-material/specular.jpeg'; var roughnessTextureUrl = 'specs/data/box-complex-material/shininess.png'; var defaultOptions = clone(obj2gltf.defaults); -defaultOptions.overridingImages = []; +defaultOptions.overridingImages = {}; var checkTransparencyOptions = clone(defaultOptions); checkTransparencyOptions.checkTransparency = true; var decodeOptions = clone(defaultOptions); diff --git a/specs/lib/loadImageSpec.js b/specs/lib/loadImageSpec.js index 369ef51..6d05426 100644 --- a/specs/lib/loadImageSpec.js +++ b/specs/lib/loadImageSpec.js @@ -11,66 +11,66 @@ var transparentImage = 'specs/data/box-complex-material/diffuse.png'; describe('loadImage', function() { it('loads png image', function(done) { expect(loadImage(pngImage) - .then(function(info) { - expect(info.transparent).toBe(false); - expect(info.source).toBeDefined(); - expect(info.extension).toBe('.png'); - expect(info.path).toBe(pngImage); - expect(info.decoded).toBeUndefined(); - expect(info.width).toBeUndefined(); - expect(info.height).toBeUndefined(); + .then(function(image) { + expect(image.transparent).toBe(false); + expect(image.source).toBeDefined(); + expect(image.extension).toBe('.png'); + expect(image.path).toBe(pngImage); + expect(image.decoded).toBeUndefined(); + expect(image.width).toBeUndefined(); + expect(image.height).toBeUndefined(); }), done).toResolve(); }); it('loads jpg image', function(done) { expect(loadImage(jpgImage) - .then(function(info) { - expect(info.transparent).toBe(false); - expect(info.source).toBeDefined(); - expect(info.extension).toBe('.jpg'); - expect(info.decoded).toBeUndefined(); - expect(info.width).toBeUndefined(); - expect(info.height).toBeUndefined(); + .then(function(image) { + expect(image.transparent).toBe(false); + expect(image.source).toBeDefined(); + expect(image.extension).toBe('.jpg'); + expect(image.decoded).toBeUndefined(); + expect(image.width).toBeUndefined(); + expect(image.height).toBeUndefined(); }), done).toResolve(); }); it('loads jpeg image', function(done) { expect(loadImage(jpegImage) - .then(function(info) { - expect(info.transparent).toBe(false); - expect(info.source).toBeDefined(); - expect(info.extension).toBe('.jpeg'); - expect(info.decoded).toBeUndefined(); - expect(info.width).toBeUndefined(); - expect(info.height).toBeUndefined(); + .then(function(image) { + expect(image.transparent).toBe(false); + expect(image.source).toBeDefined(); + expect(image.extension).toBe('.jpeg'); + expect(image.decoded).toBeUndefined(); + expect(image.width).toBeUndefined(); + expect(image.height).toBeUndefined(); }), done).toResolve(); }); it('loads gif image', function(done) { expect(loadImage(gifImage) - .then(function(info) { - expect(info.transparent).toBe(false); - expect(info.source).toBeDefined(); - expect(info.extension).toBe('.gif'); - expect(info.decoded).toBeUndefined(); - expect(info.width).toBeUndefined(); - expect(info.height).toBeUndefined(); + .then(function(image) { + expect(image.transparent).toBe(false); + expect(image.source).toBeDefined(); + expect(image.extension).toBe('.gif'); + expect(image.decoded).toBeUndefined(); + expect(image.width).toBeUndefined(); + expect(image.height).toBeUndefined(); }), done).toResolve(); }); it('loads grayscale image', function(done) { expect(loadImage(grayscaleImage) - .then(function(info) { - expect(info.transparent).toBe(false); - expect(info.source).toBeDefined(); - expect(info.extension).toBe('.png'); + .then(function(image) { + expect(image.transparent).toBe(false); + expect(image.source).toBeDefined(); + expect(image.extension).toBe('.png'); }), done).toResolve(); }); it('loads image with alpha channel', function(done) { expect(loadImage(transparentImage) - .then(function(info) { - expect(info.transparent).toBe(false); + .then(function(image) { + expect(image.transparent).toBe(false); }), done).toResolve(); }); @@ -80,8 +80,8 @@ describe('loadImage', function() { }; expect(loadImage(transparentImage, options) - .then(function(info) { - expect(info.transparent).toBe(true); + .then(function(image) { + expect(image.transparent).toBe(true); }), done).toResolve(); }); @@ -91,10 +91,10 @@ describe('loadImage', function() { }; expect(loadImage(pngImage, options) - .then(function(info) { - expect(info.decoded).toBeDefined(); - expect(info.width).toBe(211); - expect(info.height).toBe(211); + .then(function(image) { + expect(image.decoded).toBeDefined(); + expect(image.width).toBe(211); + expect(image.height).toBe(211); }), done).toResolve(); }); @@ -104,10 +104,10 @@ describe('loadImage', function() { }; expect(loadImage(jpegImage, options) - .then(function(info) { - expect(info.decoded).toBeDefined(); - expect(info.width).toBe(211); - expect(info.height).toBe(211); + .then(function(image) { + expect(image.decoded).toBeDefined(); + expect(image.width).toBe(211); + expect(image.height).toBe(211); }), done).toResolve(); }); }); diff --git a/specs/lib/obj2gltfSpec.js b/specs/lib/obj2gltfSpec.js index 3776b0c..3679b65 100644 --- a/specs/lib/obj2gltfSpec.js +++ b/specs/lib/obj2gltfSpec.js @@ -9,6 +9,10 @@ var gltfPath = 'specs/data/box-textured/box-textured.gltf'; var glbPath = 'specs/data/box-textured/box-textured.glb'; var objPathNonExistent = 'specs/data/non-existent.obj'; +var complexMaterialObjPath = 'specs/data/box-complex-material/box-complex-material.obj'; +var complexMaterialGltfPath = 'specs/data/box-complex-material/box-complex-material.gltf'; +var textureUrl = 'specs/data/box-textured/cesium.png'; + describe('obj2gltf', function() { beforeEach(function() { spyOn(fsExtra, 'outputJson').and.returnValue(Promise.resolve()); @@ -66,6 +70,26 @@ describe('obj2gltf', function() { }), done).toResolve(); }); + it('sets overriding images', function(done) { + var options = { + overridingImages : { + metallicRoughnessOcclusionTexture : textureUrl, + normalTexture : textureUrl, + baseColorTexture : textureUrl, + emissiveTexture : textureUrl + }, + separateTextures : true + }; + expect(obj2gltf(complexMaterialObjPath, complexMaterialGltfPath, options) + .then(function() { + var args = fsExtra.outputFile.calls.allArgs(); + var length = args.length; + for (var i = 0; i < length; ++i) { + expect(path.basename(args[i][0])).toBe(path.basename(textureUrl)); + } + }), done).toResolve(); + }); + it('rejects if obj path does not exist', function(done) { expect(obj2gltf(objPathNonExistent, gltfPath), done).toRejectWith(Error); });