From 05b1e3adbd454ae5fd7a5517ea1825c7550674b0 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Fri, 17 Mar 2017 16:05:51 -0400 Subject: [PATCH] Added flag checkTextureAlpha --- README.md | 1 + bin/obj2gltf.js | 8 +++++++- lib/convert.js | 3 ++- lib/image.js | 15 ++++++++++++--- lib/obj.js | 14 ++++++++------ specs/lib/imageSpec.js | 13 ++++++++++--- 6 files changed, 40 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index f73505c..44a0251 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ Using obj2gltf as a command-line tool: |`--cesium`|Optimize the glTF for Cesium by using the sun as a default light source.|No, default `false`| |`--ao`|Apply ambient occlusion to the converted model.|No, default `false`| |`--bypassPipeline`|Bypass the gltf-pipeline for debugging purposes. This option overrides many of the options above and will save the glTF with the KHR_materials_common extension.|No, default `false`| +|`--checkTextureAlpha`|Do a more exhaustive check for texture transparency by looking at the alpha channel of each pixel. By default textures with an alpha channel are considered to be transparent.|No, default `false`| ## Build Instructions diff --git a/bin/obj2gltf.js b/bin/obj2gltf.js index aa4e4c4..5d975e2 100644 --- a/bin/obj2gltf.js +++ b/bin/obj2gltf.js @@ -79,6 +79,11 @@ var argv = yargs describe: 'Bypass the gltf-pipeline for debugging purposes. This option overrides many of the options above and will save the glTF with the KHR_materials_common extension.', type: 'boolean', default: false + }, + 'checkTextureAlpha': { + describe: 'Do a more exhaustive check for texture transparency by looking at the alpha channel of each pixel. By default textures with an alpha channel are considered to be transparent.', + type: 'boolean', + default: false } }).parse(args); @@ -105,7 +110,8 @@ var options = { generateNormals : argv.n, ao : argv.ao, optimizeForCesium : argv.cesium, - bypassPipeline : argv.bypassPipeline + bypassPipeline : argv.bypassPipeline, + checkTextureAlpha : argv.checkTextureAlpha }; console.time('Total'); diff --git a/lib/convert.js b/lib/convert.js index c34d8e4..489654c 100644 --- a/lib/convert.js +++ b/lib/convert.js @@ -32,6 +32,7 @@ module.exports = convert; * @param {Boolean} [options.ao=false] Apply ambient occlusion to the converted model. * @param {Boolean} [options.textureCompressionOptions] Options sent to the compressTextures stage of gltf-pipeline. * @param {Boolean} [options.bypassPipeline=false] Bypass the gltf-pipeline for debugging purposes. This option overrides many of the options above and will save the glTF with the KHR_materials_common extension. + * @param {Boolean} [options.checkTextureAlpha=false] Do a more exhaustive check for texture transparency by looking at the alpha channel of each pixel. */ function convert(objPath, gltfPath, options) { @@ -81,7 +82,7 @@ function convert(objPath, gltfPath, options) { textureCompressionOptions : textureCompressionOptions }; - return loadObj(objPath) + return loadObj(objPath, options) .then(function(objData) { return createGltf(objData); }) diff --git a/lib/image.js b/lib/image.js index 4974d9d..1ad93ba 100644 --- a/lib/image.js +++ b/lib/image.js @@ -7,6 +7,7 @@ var Promise = require('bluebird'); var fsReadFile = Promise.promisify(fs.readFile); +var defaultValue = Cesium.defaultValue; var WebGLConstants = Cesium.WebGLConstants; module.exports = loadImage; @@ -15,11 +16,16 @@ module.exports = loadImage; * Load an image file and get information about it. * * @param {String} imagePath Path to the image file. + * @param {Object} [options] An object with the following properties: + * @param {Boolean} [options.checkTextureAlpha=false] Do a more exhaustive check for texture transparency by looking at the alpha channel of each pixel. * @returns {Promise} A promise resolving to the image information, or undefined if the file doesn't exist. * * @private */ -function loadImage(imagePath) { +function loadImage(imagePath, options) { + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + var checkTextureAlpha = defaultValue(options.checkTextureAlpha, false); + return fsReadFile(imagePath) .then(function(data) { var extension = path.extname(imagePath); @@ -38,8 +44,11 @@ function loadImage(imagePath) { info.format = getFormat(channels); if (channels === 4) { - // Need to do a finer grained check over the pixels to see if the image is actually transparent - info.transparent = isTransparent(data); + if (checkTextureAlpha) { + info.transparent = isTransparent(data); + } else { + info.transparent = true; + } } } diff --git a/lib/obj.js b/lib/obj.js index 794b9a9..e9b2159 100644 --- a/lib/obj.js +++ b/lib/obj.js @@ -51,12 +51,14 @@ var facePattern4 = /f( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/( * Parse an obj file. * * @param {String} objPath Path to the obj file. + * @param {Object} [options] An object with the following properties: + * @param {Boolean} [options.checkTextureAlpha=false] Do a more exhaustive check for texture transparency by looking at the alpha channel of each pixel. * @returns {Promise} A promise resolving to the obj data. * @exception {RuntimeError} The file does not have any geometry information in it. * * @private */ -function loadObj(objPath) { +function loadObj(objPath, options) { // Global store of vertex attributes listed in the obj file var positions = new ArrayStorage(ComponentDatatype.FLOAT); var normals = new ArrayStorage(ComponentDatatype.FLOAT); @@ -273,11 +275,11 @@ function loadObj(objPath) { uvs = undefined; // Load materials and images - return finishLoading(nodes, mtlPaths, objPath); + return finishLoading(nodes, mtlPaths, objPath, options); }); } -function finishLoading(nodes, mtlPaths, objPath) { +function finishLoading(nodes, mtlPaths, objPath, options) { nodes = cleanNodes(nodes); if (nodes.length === 0) { throw new RuntimeError(objPath + ' does not have any geometry data'); @@ -285,7 +287,7 @@ function finishLoading(nodes, mtlPaths, objPath) { return loadMaterials(mtlPaths, objPath) .then(function(materials) { var imagePaths = getImagePaths(materials); - return loadImages(imagePaths, objPath) + return loadImages(imagePaths, options) .then(function(images) { return { nodes : nodes, @@ -316,10 +318,10 @@ function loadMaterials(mtlPaths, objPath) { }); } -function loadImages(imagePaths) { +function loadImages(imagePaths, options) { var images = {}; return Promise.map(imagePaths, function(imagePath) { - return loadImage(imagePath) + return loadImage(imagePath, options) .then(function(image) { if (defined(image)) { images[imagePath] = image; diff --git a/specs/lib/imageSpec.js b/specs/lib/imageSpec.js index 9f6eb63..c046463 100644 --- a/specs/lib/imageSpec.js +++ b/specs/lib/imageSpec.js @@ -77,11 +77,18 @@ describe('image', function() { it('loads image with fully opaque alpha channel', function(done) { expect(loadImage(opaqueAlphaImage) + .then(function(info) { + expect(info.transparent).toBe(true); + }), done).toResolve(); + }); + + it('loads image with fully opaque alpha channel with checkTextureAlpha flag', function(done) { + var options = { + checkTextureAlpha : true + }; + expect(loadImage(opaqueAlphaImage, options) .then(function(info) { expect(info.transparent).toBe(false); - expect(info.format).toBe(WebGLConstants.RGBA); - expect(info.source).toBeDefined(); - expect(info.extension).toBe('.png'); }), done).toResolve(); });