From b913b0fa5ff8584d6c94433542d3f8a1fd3d17a8 Mon Sep 17 00:00:00 2001 From: Tom Fili Date: Fri, 19 Jul 2019 13:07:34 -0400 Subject: [PATCH 01/14] Added a check to see if diffuse and alpha texture is the same. --- lib/loadMtl.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/loadMtl.js b/lib/loadMtl.js index dc42545..1e55990 100644 --- a/lib/loadMtl.js +++ b/lib/loadMtl.js @@ -387,6 +387,10 @@ function createDiffuseAlphaTexture(diffuseTexture, alphaTexture, options) { return diffuseTexture; } + if (diffuseTexture.path === alphaTexture.path) { + return diffuseTexture; + } + if (!defined(diffuseTexture.pixels) || !defined(alphaTexture.pixels)) { options.logger('Could not get decoded texture data for ' + diffuseTexture.path + ' or ' + alphaTexture.path + '. The material will be created without an alpha texture.'); return diffuseTexture; From b0de7d1bc1373855b2b7197588d427b1e89f8383 Mon Sep 17 00:00:00 2001 From: Tom Fili Date: Fri, 19 Jul 2019 13:15:38 -0400 Subject: [PATCH 02/14] Added test --- specs/lib/loadMtlSpec.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/specs/lib/loadMtlSpec.js b/specs/lib/loadMtlSpec.js index 2af7f0a..72cedcd 100644 --- a/specs/lib/loadMtlSpec.js +++ b/specs/lib/loadMtlSpec.js @@ -321,6 +321,18 @@ describe('loadMtl', () => { expect(material.alphaMode).toBe('BLEND'); expect(material.doubleSided).toBe(true); }); + + it('uses diffuse texture if diffuse and alpha are the same', () => { + options.metallicRoughness = true; + + const material = loadMtl._createMaterial({ + diffuseTexture : diffuseTexture, + alphaTexture : diffuseTexture + }, options); + + const pbr = material.pbrMetallicRoughness; + expect(pbr.baseColorTexture).toBe(diffuseTexture); + }); }); describe('specularGlossiness', () => { From 0fa1ec528d8e87fe7da4a2578c317699d1a8b37d Mon Sep 17 00:00:00 2001 From: Tom Fili Date: Fri, 19 Jul 2019 14:52:12 -0400 Subject: [PATCH 03/14] Made alpha images work if same as diffuse --- lib/loadMtl.js | 13 +++++++------ specs/lib/loadMtlSpec.js | 26 +++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/lib/loadMtl.js b/lib/loadMtl.js index 1e55990..d8ea67a 100644 --- a/lib/loadMtl.js +++ b/lib/loadMtl.js @@ -388,6 +388,7 @@ function createDiffuseAlphaTexture(diffuseTexture, alphaTexture, options) { } if (diffuseTexture.path === alphaTexture.path) { + diffuseTexture.transparent = true; return diffuseTexture; } @@ -590,7 +591,7 @@ function createSpecularGlossinessMaterial(material, options) { emissiveFactor = [1.0, 1.0, 1.0]; } - if (defined(diffuseTexture)) { + if (defined(diffuseAlphaTexture)) { diffuseFactor = [1.0, 1.0, 1.0, 1.0]; } @@ -611,8 +612,8 @@ function createSpecularGlossinessMaterial(material, options) { transparent = alpha < 1.0; } - if (defined(diffuseTexture)) { - transparent = transparent || diffuseTexture.transparent; + if (defined(diffuseAlphaTexture)) { + transparent = transparent || diffuseAlphaTexture.transparent; } const doubleSided = transparent; @@ -662,7 +663,7 @@ function createMetallicRoughnessMaterial(material, options) { emissiveFactor = [1.0, 1.0, 1.0]; } - if (defined(baseColorTexture)) { + if (defined(diffuseAlphaTexture)) { baseColorFactor = [1.0, 1.0, 1.0, 1.0]; } @@ -683,8 +684,8 @@ function createMetallicRoughnessMaterial(material, options) { transparent = alpha < 1.0; } - if (defined(baseColorTexture)) { - transparent = transparent || baseColorTexture.transparent; + if (defined(diffuseAlphaTexture)) { + transparent = transparent || diffuseAlphaTexture.transparent; } const doubleSided = transparent; diff --git a/specs/lib/loadMtlSpec.js b/specs/lib/loadMtlSpec.js index 72cedcd..6d7eb7e 100644 --- a/specs/lib/loadMtlSpec.js +++ b/specs/lib/loadMtlSpec.js @@ -322,16 +322,20 @@ describe('loadMtl', () => { expect(material.doubleSided).toBe(true); }); - it('uses diffuse texture if diffuse and alpha are the same', () => { + it('uses diffuse texture if diffuse and alpha are the same', async () => { options.metallicRoughness = true; + // The transparent property will be modified so make a copy + const diffuseTextureCopy = await loadTexture(diffuseTexturePath, decodeOptions); const material = loadMtl._createMaterial({ - diffuseTexture : diffuseTexture, + diffuseTexture : diffuseTextureCopy, alphaTexture : diffuseTexture }, options); const pbr = material.pbrMetallicRoughness; - expect(pbr.baseColorTexture).toBe(diffuseTexture); + expect(pbr.baseColorTexture).toBe(diffuseTextureCopy); + expect(material.alphaMode).toBe('BLEND'); + expect(material.doubleSided).toBe(true); }); }); @@ -428,5 +432,21 @@ describe('loadMtl', () => { expect(material.alphaMode).toBe('BLEND'); expect(material.doubleSided).toBe(true); }); + + it('uses diffuse texture if diffuse and alpha are the same', async () => { + options.specularGlossiness = true; + + // The transparent property will be modified so make a copy + const diffuseTextureCopy = await loadTexture(diffuseTexturePath, decodeOptions); + const material = loadMtl._createMaterial({ + diffuseTexture : diffuseTextureCopy, + alphaTexture : diffuseTexture + }, options); + + const pbr = material.extensions.KHR_materials_pbrSpecularGlossiness; + expect(pbr.diffuseTexture).toEqual(diffuseTextureCopy); + expect(material.alphaMode).toBe('BLEND'); + expect(material.doubleSided).toBe(true); + }); }); }); From 3ba174dd3347026a9b4cc4febcd22c1b256f83f9 Mon Sep 17 00:00:00 2001 From: Tom Fili Date: Fri, 19 Jul 2019 21:03:33 -0400 Subject: [PATCH 04/14] Removed unneeded code --- lib/loadMtl.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/loadMtl.js b/lib/loadMtl.js index d8ea67a..17a31e7 100644 --- a/lib/loadMtl.js +++ b/lib/loadMtl.js @@ -388,7 +388,6 @@ function createDiffuseAlphaTexture(diffuseTexture, alphaTexture, options) { } if (diffuseTexture.path === alphaTexture.path) { - diffuseTexture.transparent = true; return diffuseTexture; } From 72f09e2b1e70f73b37d9765085c5186cd4ca16fa Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 22 Jul 2019 18:32:29 -0400 Subject: [PATCH 05/14] Delete webstorm file --- .idea/inspectionProfiles/profiles_settings.xml | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 .idea/inspectionProfiles/profiles_settings.xml diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 3b31283..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file From 080f5debf7cd590cc946aeb2c571d92a7bada74d Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 22 Jul 2019 18:39:30 -0400 Subject: [PATCH 06/14] Revert some changes from diffuse-alpha-same --- lib/loadMtl.js | 14 +++++++------- specs/lib/loadMtlSpec.js | 16 ++++++---------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/lib/loadMtl.js b/lib/loadMtl.js index 17a31e7..e220536 100644 --- a/lib/loadMtl.js +++ b/lib/loadMtl.js @@ -387,7 +387,7 @@ function createDiffuseAlphaTexture(diffuseTexture, alphaTexture, options) { return diffuseTexture; } - if (diffuseTexture.path === alphaTexture.path) { + if (diffuseTexture === alphaTexture) { return diffuseTexture; } @@ -590,7 +590,7 @@ function createSpecularGlossinessMaterial(material, options) { emissiveFactor = [1.0, 1.0, 1.0]; } - if (defined(diffuseAlphaTexture)) { + if (defined(diffuseTexture)) { diffuseFactor = [1.0, 1.0, 1.0, 1.0]; } @@ -611,8 +611,8 @@ function createSpecularGlossinessMaterial(material, options) { transparent = alpha < 1.0; } - if (defined(diffuseAlphaTexture)) { - transparent = transparent || diffuseAlphaTexture.transparent; + if (defined(diffuseTexture)) { + transparent = transparent || diffuseTexture.transparent; } const doubleSided = transparent; @@ -662,7 +662,7 @@ function createMetallicRoughnessMaterial(material, options) { emissiveFactor = [1.0, 1.0, 1.0]; } - if (defined(diffuseAlphaTexture)) { + if (defined(baseColorTexture)) { baseColorFactor = [1.0, 1.0, 1.0, 1.0]; } @@ -683,8 +683,8 @@ function createMetallicRoughnessMaterial(material, options) { transparent = alpha < 1.0; } - if (defined(diffuseAlphaTexture)) { - transparent = transparent || diffuseAlphaTexture.transparent; + if (defined(baseColorTexture)) { + transparent = transparent || baseColorTexture.transparent; } const doubleSided = transparent; diff --git a/specs/lib/loadMtlSpec.js b/specs/lib/loadMtlSpec.js index 6d7eb7e..fb46c90 100644 --- a/specs/lib/loadMtlSpec.js +++ b/specs/lib/loadMtlSpec.js @@ -322,18 +322,16 @@ describe('loadMtl', () => { expect(material.doubleSided).toBe(true); }); - it('uses diffuse texture if diffuse and alpha are the same', async () => { + it('uses diffuse texture if diffuse and alpha are the same', () => { options.metallicRoughness = true; - // The transparent property will be modified so make a copy - const diffuseTextureCopy = await loadTexture(diffuseTexturePath, decodeOptions); const material = loadMtl._createMaterial({ - diffuseTexture : diffuseTextureCopy, + diffuseTexture : diffuseTexture, alphaTexture : diffuseTexture }, options); const pbr = material.pbrMetallicRoughness; - expect(pbr.baseColorTexture).toBe(diffuseTextureCopy); + expect(pbr.baseColorTexture).toBe(diffuseTexture); expect(material.alphaMode).toBe('BLEND'); expect(material.doubleSided).toBe(true); }); @@ -433,18 +431,16 @@ describe('loadMtl', () => { expect(material.doubleSided).toBe(true); }); - it('uses diffuse texture if diffuse and alpha are the same', async () => { + it('uses diffuse texture if diffuse and alpha are the same', () => { options.specularGlossiness = true; - // The transparent property will be modified so make a copy - const diffuseTextureCopy = await loadTexture(diffuseTexturePath, decodeOptions); const material = loadMtl._createMaterial({ - diffuseTexture : diffuseTextureCopy, + diffuseTexture : diffuseTexture, alphaTexture : diffuseTexture }, options); const pbr = material.extensions.KHR_materials_pbrSpecularGlossiness; - expect(pbr.diffuseTexture).toEqual(diffuseTextureCopy); + expect(pbr.diffuseTexture).toEqual(diffuseTexture); expect(material.alphaMode).toBe('BLEND'); expect(material.doubleSided).toBe(true); }); From 1d0bb5eb359595a2191016581d801ffd1206d751 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 22 Jul 2019 18:44:09 -0400 Subject: [PATCH 07/14] Update CHANGES and package.json --- CHANGES.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index cf35100..536395f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,10 @@ Change Log ========== +### 3.0.4 - 2019-07-22 + +* No longer printing texture decode warning if the diffuse and alpha textures are the same. [#205](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/205) + ### 3.0.3 2019-06-26 * Fixed parsing of negative face indices. [#191](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/191) diff --git a/package.json b/package.json index 430602f..14f1854 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obj2gltf", - "version": "3.0.3", + "version": "3.0.4", "description": "Convert OBJ model format to glTF", "license": "Apache-2.0", "contributors": [ From 3cf338107d61e4626ccd43a79e58e85538b56c33 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 20 Apr 2017 14:41:39 -0400 Subject: [PATCH 08/14] Added up axis options back --- bin/obj2gltf.js | 75 ++++++++-------------------------------- lib/loadObj.js | 58 ++++++++++++++++++++++++++----- lib/obj2gltf.js | 18 +++++++++- specs/lib/loadObjSpec.js | 52 ++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 69 deletions(-) diff --git a/bin/obj2gltf.js b/bin/obj2gltf.js index 47acf97..91694b3 100644 --- a/bin/obj2gltf.js +++ b/bin/obj2gltf.js @@ -66,62 +66,21 @@ const argv = yargs default : defaults.checkTransparency }, secure : { - describe : 'Prevent the converter from reading textures or mtl files outside of the input obj directory.', - type : 'boolean', - default : defaults.secure + describe: 'Prevent the converter from reading image or mtl files outside of the input obj directory.', + type: 'boolean', + default: defaults.secure }, - packOcclusion : { - describe : 'Pack the occlusion texture in the red channel of metallic-roughness texture.', - type : 'boolean', - default : defaults.packOcclusion + inputUpAxis : { + describe: 'Up axis of the obj.', + choices: ['X', 'Y', 'Z'], + type: 'string', + default: 'Y' }, - 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.', - type : 'boolean', - default : defaults.metallicRoughness - }, - 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.', - type : 'boolean', - default : defaults.specularGlossiness - }, - metallicRoughnessOcclusionTexture : { - describe : 'Path to the metallic-roughness-occlusion texture that should override textures in the .mtl file, 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. 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', - type : 'string', - normalize : true - }, - specularGlossinessTexture : { - describe : 'Path to the specular-glossiness texture that should override textures in the .mtl file, 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.', - type : 'string', - normalize : true - }, - occlusionTexture : { - describe : 'Path to the occlusion texture that should override textures in the .mtl file.', - type : 'string', - normalize : true - }, - normalTexture : { - describe : 'Path to the normal texture that should override textures in the .mtl file.', - type : 'string', - normalize : true - }, - baseColorTexture : { - describe : 'Path to the baseColor/diffuse texture that should override textures in the .mtl file.', - type : 'string', - normalize : true - }, - emissiveTexture : { - describe : 'Path to the emissive texture that should override textures in the .mtl file.', - type : 'string', - normalize : true - }, - alphaTexture : { - describe : 'Path to the alpha texture that should override textures in the .mtl file.' - }, - unlit : { - describe : 'The glTF will be saved with the KHR_materials_unlit extension.', - type : 'boolean', - default : defaults.unlit + outputUpAxis : { + describe: 'Up axis of the converted glTF.', + choices: ['X', 'Y', 'Z'], + type: 'string', + default: 'Y' } }).parse(args); @@ -162,12 +121,8 @@ const options = { separateTextures : argv.separateTextures, checkTransparency : argv.checkTransparency, secure : argv.secure, - packOcclusion : argv.packOcclusion, - metallicRoughness : argv.metallicRoughness, - specularGlossiness : argv.specularGlossiness, - unlit : argv.unlit, - overridingTextures : overridingTextures, - outputDirectory : outputDirectory + inputUpAxis : argv.inputUpAxis, + outputUpAxis : argv.outputUpAxis }; console.time('Total'); diff --git a/lib/loadObj.js b/lib/loadObj.js index 90e4969..2207685 100644 --- a/lib/loadObj.js +++ b/lib/loadObj.js @@ -8,6 +8,7 @@ const loadMtl = require('./loadMtl'); const outsideDirectory = require('./outsideDirectory'); const readLines = require('./readLines'); +const Axis = Cesium.Axis; const Cartesian3 = Cesium.Cartesian3; const ComponentDatatype = Cesium.ComponentDatatype; const CoplanarPolygonGeometryLibrary = Cesium.CoplanarPolygonGeometryLibrary; @@ -16,6 +17,8 @@ const defined = Cesium.defined; const PolygonPipeline = Cesium.PolygonPipeline; const RuntimeError = Cesium.RuntimeError; const WindingOrder = Cesium.WindingOrder; +const Matrix4 = Cesium.Matrix4; + module.exports = loadObj; @@ -47,16 +50,31 @@ const normalPattern = /vn( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\ const uvPattern = /vt( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vt float float const facePattern = /(-?\d+)\/?(-?\d*)\/?(-?\d*)/g; // for any face format "f v", "f v/v", "f v//v", "f v/v/v" +var scratchCartesian = new Cartesian3(); + /** * Parse an obj file. * * @param {String} objPath Path to the obj file. +<<<<<<< HEAD * @param {Object} options The options object passed along from lib/obj2gltf.js * @returns {Promise} A promise resolving to the obj data, which includes an array of nodes containing geometry information and an array of materials. +======= + * @param {Object} options An object with the following properties: + * @param {Boolean} options.checkTransparency Do a more exhaustive check for texture transparency by looking at the alpha channel of each pixel. + * @param {Boolean} options.secure Prevent the converter from reading image or mtl files outside of the input obj directory. + * @param {String} options.inputUpAxis Up axis of the obj. + * @param {String} options.outputUpAxis Up axis of the converted glTF. + * @param {Boolean} options.logger A callback function for handling logged messages. Defaults to console.log. + * @returns {Promise} A promise resolving to the obj data. + * @exception {RuntimeError} The file does not have any geometry information in it. +>>>>>>> 93dac5e... Convert up axis * * @private */ function loadObj(objPath, options) { + var axisTransform = getAxisTransform(options.inputUpAxis, options.outputUpAxis); + // Global store of vertex attributes listed in the obj file let globalPositions = new ArrayStorage(ComponentDatatype.FLOAT); let globalNormals = new ArrayStorage(ComponentDatatype.FLOAT); @@ -354,15 +372,23 @@ function loadObj(objPath, options) { const mtllibLine = line.substring(7).trim(); mtlPaths = mtlPaths.concat(getMtlPaths(mtllibLine)); } else if ((result = vertexPattern.exec(line)) !== null) { - globalPositions.push(parseFloat(result[1])); - globalPositions.push(parseFloat(result[2])); - globalPositions.push(parseFloat(result[3])); + const position = scratchCartesian; + position.x = parseFloat(result[1]); + position.y = parseFloat(result[2]); + position.z = parseFloat(result[3]); + if (defined(axisTransform)) { + Matrix4.multiplyByPoint(axisTransform, position, position); + } + globalPositions.push(position.x); + globalPositions.push(position.y); + globalPositions.push(position.z); } else if ((result = normalPattern.exec(line) ) !== null) { - const normal = Cartesian3.fromElements(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3]), scratchNormal); - if (Cartesian3.equals(normal, Cartesian3.ZERO)) { - Cartesian3.clone(Cartesian3.UNIT_Z, normal); - } else { - Cartesian3.normalize(normal, normal); + const normal = scratchCartesian; + normal.x = parseFloat(result[1]); + normal.y = parseFloat(result[2]); + normal.z = parseFloat(result[3]); + if (defined(axisTransform)) { + Matrix4.multiplyByPointAsVector(axisTransform, normal, normal); } globalNormals.push(normal.x); globalNormals.push(normal.y); @@ -625,3 +651,19 @@ function cleanNodes(nodes) { setDefaults(nodes); return nodes; } + +function getAxisTransform(inputUpAxis, outputUpAxis) { + if (inputUpAxis === 'X' && outputUpAxis === 'Y') { + return Axis.X_UP_TO_Y_UP; + } else if (inputUpAxis === 'X' && outputUpAxis === 'Z') { + return Axis.X_UP_TO_Z_UP; + } else if (inputUpAxis === 'Y' && outputUpAxis === 'X') { + return Axis.Y_UP_TO_X_UP; + } else if (inputUpAxis === 'Y' && outputUpAxis === 'Z') { + return Axis.Y_UP_TO_Z_UP; + } else if (inputUpAxis === 'Z' && outputUpAxis === 'X') { + return Axis.Z_UP_TO_X_UP; + } else if (inputUpAxis === 'Z' && outputUpAxis === 'Y') { + return Axis.Z_UP_TO_Y_UP; + } +} diff --git a/lib/obj2gltf.js b/lib/obj2gltf.js index 0f5a66c..963656f 100644 --- a/lib/obj2gltf.js +++ b/lib/obj2gltf.js @@ -34,6 +34,8 @@ module.exports = obj2gltf; * @param {String} [options.overridingTextures.baseColorTexture] Path to the baseColor/diffuse texture. * @param {String} [options.overridingTextures.emissiveTexture] Path to the emissive texture. * @param {String} [options.overridingTextures.alphaTexture] Path to the alpha texture. + * @param {String} [options.inputUpAxis='Y'] Up axis of the obj. Choices are 'X', 'Y', and 'Z'. + * @param {String} [options.outputUpAxis='Z'] Up axis of the converted glTF. Choices are 'X', 'Y', and 'Z'. * @param {Logger} [options.logger] A callback function for handling logged messages. Defaults to console.log. * @param {Writer} [options.writer] A callback function that writes files that are saved as separate resources. * @param {String} [options.outputDirectory] Output directory for writing separate resources when options.writer is not defined. @@ -54,6 +56,8 @@ function obj2gltf(objPath, options) { options.overridingTextures = defaultValue(options.overridingTextures, defaultValue.EMPTY_OBJECT); options.logger = defaultValue(options.logger, getDefaultLogger()); options.writer = defaultValue(options.writer, getDefaultWriter(options.outputDirectory)); + options.inputUpAxis = defaultValue(options.inputUpAxis, defaults.inputUpAxis); + options.outputUpAxis = defaultValue(options.outputUpAxis, defaults.outputUpAxis); if (!defined(objPath)) { throw new DeveloperError('objPath is required'); @@ -164,7 +168,19 @@ obj2gltf.defaults = { * @type Boolean * @default false */ - unlit : false + unlit : false, + /** + * Gets or sets the up axis of the obj. + * @type String + * @default 'Y' + */ + inputUpAxis: 'Y', + /** + * Gets or sets the up axis of the converted glTF. + * @type String + * @default 'Y' + */ + outputUpAxis: 'Y', }; /** diff --git a/specs/lib/loadObjSpec.js b/specs/lib/loadObjSpec.js index 7a84397..720e644 100644 --- a/specs/lib/loadObjSpec.js +++ b/specs/lib/loadObjSpec.js @@ -445,6 +445,7 @@ describe('loadObj', () => { expect(baseColorTexture.source).toBeDefined(); }); +<<<<<<< HEAD it('separates faces that don\'t use the same attributes as other faces in the primitive', async () => { const data = await loadObj(objMixedAttributesPath, options); const primitives = getPrimitives(data); @@ -453,6 +454,57 @@ describe('loadObj', () => { expect(primitives[1].indices.length).toBe(6); // 2 faces expect(primitives[2].indices.length).toBe(6); // 2 faces expect(primitives[3].indices.length).toBe(6); // 2 faces +======= + function getFirstPosition(data) { + var positions = data.nodes[0].meshes[0].positions; + return new Cartesian3(positions.get(0), positions.get(1), positions.get(2)); + } + + function getFirstNormal(data) { + var normals = data.nodes[0].meshes[0].normals; + return new Cartesian3(normals.get(0), normals.get(1), normals.get(2)); + } + + function checkAxisConversion(inputUpAxis, outputUpAxis, position, normal) { + var sameAxis = (inputUpAxis === outputUpAxis); + var options = clone(defaultOptions); + options.inputUpAxis = inputUpAxis; + options.outputUpAxis = outputUpAxis; + return loadObj(objRotatedUrl, options) + .then(function(data) { + var rotatedPosition = getFirstPosition(data); + var rotatedNormal = getFirstNormal(data); + if (sameAxis) { + expect(rotatedPosition).toEqual(position); + expect(rotatedNormal).toEqual(normal); + } else { + expect(rotatedPosition).not.toEqual(position); + expect(rotatedNormal).not.toEqual(normal); + } + }); + } + + it('performs up axis conversion', function(done) { + expect(loadObj(objRotatedUrl, defaultOptions) + .then(function(data) { + var position = getFirstPosition(data); + var normal = getFirstNormal(data); + + var axes = ['X', 'Y', 'Z']; + var axesLength = axes.length; + var promises = []; + for (var i = 0; i < axesLength; ++i) { + for (var j = 0; j < axesLength; ++j) { + promises.push(checkAxisConversion(axes[i], axes[j], position, normal)); + } + } + return Promise.all(promises); + }), done).toResolve(); + }); + + it('throws when file has invalid contents', function(done) { + expect(loadObj(objInvalidContentsUrl, defaultOptions), done).toRejectWith(RuntimeError); +>>>>>>> 93dac5e... Convert up axis }); it('throws when file has invalid contents', async () => { From 5c179693a3e1eb3dcac1573d6f781e5f9e289b44 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2019 23:18:03 +0000 Subject: [PATCH 09/14] fix(package): update yargs to version 14.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 14f1854..667da36 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "jpeg-js": "^0.3.5", "mime": "^2.4.4", "pngjs": "^3.4.0", - "yargs": "^13.2.4" + "yargs": "^14.0.0" }, "devDependencies": { "cloc": "^2.5.0", From 876cbefe7431e1e7af6497ed4a39434500cdfc99 Mon Sep 17 00:00:00 2001 From: Jesse Vander Does Date: Mon, 19 Aug 2019 16:33:12 -0700 Subject: [PATCH 10/14] Restored lost code and fixed tests --- bin/obj2gltf.js | 65 +++++++++++++++++++++++++++++++++++-- lib/loadObj.js | 25 +++++---------- specs/lib/loadObjSpec.js | 69 +++++++++++++++++----------------------- 3 files changed, 99 insertions(+), 60 deletions(-) diff --git a/bin/obj2gltf.js b/bin/obj2gltf.js index 91694b3..40ffe76 100644 --- a/bin/obj2gltf.js +++ b/bin/obj2gltf.js @@ -66,9 +66,62 @@ const argv = yargs default : defaults.checkTransparency }, secure : { - describe: 'Prevent the converter from reading image or mtl files outside of the input obj directory.', - type: 'boolean', - default: defaults.secure + describe : 'Prevent the converter from reading textures or mtl files outside of the input obj directory.', + type : 'boolean', + default : defaults.secure + }, + packOcclusion : { + describe : 'Pack the occlusion texture in the red channel of metallic-roughness texture.', + type : 'boolean', + default : defaults.packOcclusion + }, + 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.', + type : 'boolean', + default : defaults.metallicRoughness + }, + 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.', + type : 'boolean', + default : defaults.specularGlossiness + }, + metallicRoughnessOcclusionTexture : { + describe : 'Path to the metallic-roughness-occlusion texture that should override textures in the .mtl file, 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. 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', + type : 'string', + normalize : true + }, + specularGlossinessTexture : { + describe : 'Path to the specular-glossiness texture that should override textures in the .mtl file, 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.', + type : 'string', + normalize : true + }, + occlusionTexture : { + describe : 'Path to the occlusion texture that should override textures in the .mtl file.', + type : 'string', + normalize : true + }, + normalTexture : { + describe : 'Path to the normal texture that should override textures in the .mtl file.', + type : 'string', + normalize : true + }, + baseColorTexture : { + describe : 'Path to the baseColor/diffuse texture that should override textures in the .mtl file.', + type : 'string', + normalize : true + }, + emissiveTexture : { + describe : 'Path to the emissive texture that should override textures in the .mtl file.', + type : 'string', + normalize : true + }, + alphaTexture : { + describe : 'Path to the alpha texture that should override textures in the .mtl file.' + }, + unlit : { + describe : 'The glTF will be saved with the KHR_materials_unlit extension.', + type : 'boolean', + default : defaults.unlit }, inputUpAxis : { describe: 'Up axis of the obj.', @@ -121,6 +174,12 @@ const options = { separateTextures : argv.separateTextures, checkTransparency : argv.checkTransparency, secure : argv.secure, + packOcclusion : argv.packOcclusion, + metallicRoughness : argv.metallicRoughness, + specularGlossiness : argv.specularGlossiness, + unlit : argv.unlit, + overridingTextures : overridingTextures, + outputDirectory : outputDirectory, inputUpAxis : argv.inputUpAxis, outputUpAxis : argv.outputUpAxis }; diff --git a/lib/loadObj.js b/lib/loadObj.js index 2207685..67e8a8b 100644 --- a/lib/loadObj.js +++ b/lib/loadObj.js @@ -50,30 +50,19 @@ const normalPattern = /vn( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\ const uvPattern = /vt( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vt float float const facePattern = /(-?\d+)\/?(-?\d*)\/?(-?\d*)/g; // for any face format "f v", "f v/v", "f v//v", "f v/v/v" -var scratchCartesian = new Cartesian3(); +const scratchCartesian = new Cartesian3(); /** * Parse an obj file. * * @param {String} objPath Path to the obj file. -<<<<<<< HEAD * @param {Object} options The options object passed along from lib/obj2gltf.js * @returns {Promise} A promise resolving to the obj data, which includes an array of nodes containing geometry information and an array of materials. -======= - * @param {Object} options An object with the following properties: - * @param {Boolean} options.checkTransparency Do a more exhaustive check for texture transparency by looking at the alpha channel of each pixel. - * @param {Boolean} options.secure Prevent the converter from reading image or mtl files outside of the input obj directory. - * @param {String} options.inputUpAxis Up axis of the obj. - * @param {String} options.outputUpAxis Up axis of the converted glTF. - * @param {Boolean} options.logger A callback function for handling logged messages. Defaults to console.log. - * @returns {Promise} A promise resolving to the obj data. - * @exception {RuntimeError} The file does not have any geometry information in it. ->>>>>>> 93dac5e... Convert up axis * * @private */ function loadObj(objPath, options) { - var axisTransform = getAxisTransform(options.inputUpAxis, options.outputUpAxis); + const axisTransform = getAxisTransform(options.inputUpAxis, options.outputUpAxis); // Global store of vertex attributes listed in the obj file let globalPositions = new ArrayStorage(ComponentDatatype.FLOAT); @@ -383,10 +372,12 @@ function loadObj(objPath, options) { globalPositions.push(position.y); globalPositions.push(position.z); } else if ((result = normalPattern.exec(line) ) !== null) { - const normal = scratchCartesian; - normal.x = parseFloat(result[1]); - normal.y = parseFloat(result[2]); - normal.z = parseFloat(result[3]); + const normal = Cartesian3.fromElements(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3]), scratchNormal); + if (Cartesian3.equals(normal, Cartesian3.ZERO)) { + Cartesian3.clone(Cartesian3.UNIT_Z, normal); + } else { + Cartesian3.normalize(normal, normal); + } if (defined(axisTransform)) { Matrix4.multiplyByPointAsVector(axisTransform, normal, normal); } diff --git a/specs/lib/loadObjSpec.js b/specs/lib/loadObjSpec.js index 720e644..cfcdebc 100644 --- a/specs/lib/loadObjSpec.js +++ b/specs/lib/loadObjSpec.js @@ -10,6 +10,7 @@ const clone = Cesium.clone; const RuntimeError = Cesium.RuntimeError; const objPath = 'specs/data/box/box.obj'; +const objRotatedUrl = 'specs/data/box-rotated/box-rotated.obj'; const objNormalsPath = 'specs/data/box-normals/box-normals.obj'; const objUvsPath = 'specs/data/box-uvs/box-uvs.obj'; const objPositionsOnlyPath = 'specs/data/box-positions-only/box-positions-only.obj'; @@ -445,7 +446,6 @@ describe('loadObj', () => { expect(baseColorTexture.source).toBeDefined(); }); -<<<<<<< HEAD it('separates faces that don\'t use the same attributes as other faces in the primitive', async () => { const data = await loadObj(objMixedAttributesPath, options); const primitives = getPrimitives(data); @@ -454,57 +454,46 @@ describe('loadObj', () => { expect(primitives[1].indices.length).toBe(6); // 2 faces expect(primitives[2].indices.length).toBe(6); // 2 faces expect(primitives[3].indices.length).toBe(6); // 2 faces -======= + }); + function getFirstPosition(data) { - var positions = data.nodes[0].meshes[0].positions; - return new Cartesian3(positions.get(0), positions.get(1), positions.get(2)); + const primitive = getPrimitives(data)[0]; + return new Cartesian3(primitive.positions.get(0), primitive.positions.get(1), primitive.positions.get(2)); } function getFirstNormal(data) { - var normals = data.nodes[0].meshes[0].normals; - return new Cartesian3(normals.get(0), normals.get(1), normals.get(2)); + const primitive = getPrimitives(data)[0]; + return new Cartesian3(primitive.normals.get(0), primitive.normals.get(1), primitive.normals.get(2)); } - function checkAxisConversion(inputUpAxis, outputUpAxis, position, normal) { + async function checkAxisConversion(inputUpAxis, outputUpAxis, position, normal) { var sameAxis = (inputUpAxis === outputUpAxis); - var options = clone(defaultOptions); options.inputUpAxis = inputUpAxis; options.outputUpAxis = outputUpAxis; - return loadObj(objRotatedUrl, options) - .then(function(data) { - var rotatedPosition = getFirstPosition(data); - var rotatedNormal = getFirstNormal(data); - if (sameAxis) { - expect(rotatedPosition).toEqual(position); - expect(rotatedNormal).toEqual(normal); - } else { - expect(rotatedPosition).not.toEqual(position); - expect(rotatedNormal).not.toEqual(normal); - } - }); + const data = await loadObj(objRotatedUrl, options); + const rotatedPosition = getFirstPosition(data); + const rotatedNormal = getFirstNormal(data); + if (sameAxis) { + expect(rotatedPosition).toEqual(position); + expect(rotatedNormal).toEqual(normal); + } else { + expect(rotatedPosition).not.toEqual(position); + expect(rotatedNormal).not.toEqual(normal); + } } - it('performs up axis conversion', function(done) { - expect(loadObj(objRotatedUrl, defaultOptions) - .then(function(data) { - var position = getFirstPosition(data); - var normal = getFirstNormal(data); + it('performs up axis conversion', async () => { + const data = await loadObj(objRotatedUrl, options); + const position = getFirstPosition(data); + const normal = getFirstNormal(data); - var axes = ['X', 'Y', 'Z']; - var axesLength = axes.length; - var promises = []; - for (var i = 0; i < axesLength; ++i) { - for (var j = 0; j < axesLength; ++j) { - promises.push(checkAxisConversion(axes[i], axes[j], position, normal)); - } - } - return Promise.all(promises); - }), done).toResolve(); - }); - - it('throws when file has invalid contents', function(done) { - expect(loadObj(objInvalidContentsUrl, defaultOptions), done).toRejectWith(RuntimeError); ->>>>>>> 93dac5e... Convert up axis + const axes = ['X', 'Y', 'Z']; + const axesLength = axes.length; + for (let i = 0; i < axesLength; ++i) { + for (let j = 0; j < axesLength; ++j) { + await checkAxisConversion(axes[i], axes[j], position, normal); + } + } }); it('throws when file has invalid contents', async () => { From a1b1860da2afcf1f51fe0e2575ed44765c1ac7b9 Mon Sep 17 00:00:00 2001 From: Jesse Vander Does Date: Tue, 20 Aug 2019 10:32:32 -0700 Subject: [PATCH 11/14] Fixed code styling --- lib/loadObj.js | 1 - lib/obj2gltf.js | 2 +- specs/lib/loadObjSpec.js | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/loadObj.js b/lib/loadObj.js index 67e8a8b..1052017 100644 --- a/lib/loadObj.js +++ b/lib/loadObj.js @@ -19,7 +19,6 @@ const RuntimeError = Cesium.RuntimeError; const WindingOrder = Cesium.WindingOrder; const Matrix4 = Cesium.Matrix4; - module.exports = loadObj; // Object name (o) -> node diff --git a/lib/obj2gltf.js b/lib/obj2gltf.js index 963656f..c2f9b4d 100644 --- a/lib/obj2gltf.js +++ b/lib/obj2gltf.js @@ -180,7 +180,7 @@ obj2gltf.defaults = { * @type String * @default 'Y' */ - outputUpAxis: 'Y', + outputUpAxis: 'Y' }; /** diff --git a/specs/lib/loadObjSpec.js b/specs/lib/loadObjSpec.js index cfcdebc..ca6f046 100644 --- a/specs/lib/loadObjSpec.js +++ b/specs/lib/loadObjSpec.js @@ -467,7 +467,7 @@ describe('loadObj', () => { } async function checkAxisConversion(inputUpAxis, outputUpAxis, position, normal) { - var sameAxis = (inputUpAxis === outputUpAxis); + const sameAxis = (inputUpAxis === outputUpAxis); options.inputUpAxis = inputUpAxis; options.outputUpAxis = outputUpAxis; const data = await loadObj(objRotatedUrl, options); From fd6e98688d4b03083d67906de374faa767738c50 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 26 Aug 2019 07:56:03 -0400 Subject: [PATCH 12/14] Fix default value in doc --- lib/obj2gltf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/obj2gltf.js b/lib/obj2gltf.js index c2f9b4d..cdb57e8 100644 --- a/lib/obj2gltf.js +++ b/lib/obj2gltf.js @@ -35,7 +35,7 @@ module.exports = obj2gltf; * @param {String} [options.overridingTextures.emissiveTexture] Path to the emissive texture. * @param {String} [options.overridingTextures.alphaTexture] Path to the alpha texture. * @param {String} [options.inputUpAxis='Y'] Up axis of the obj. Choices are 'X', 'Y', and 'Z'. - * @param {String} [options.outputUpAxis='Z'] 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 {Logger} [options.logger] A callback function for handling logged messages. Defaults to console.log. * @param {Writer} [options.writer] A callback function that writes files that are saved as separate resources. * @param {String} [options.outputDirectory] Output directory for writing separate resources when options.writer is not defined. From 705901023bb568ee7b269bbe71f2224cef10ca2e Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Mon, 26 Aug 2019 18:18:44 -0400 Subject: [PATCH 13/14] Update CHANGES.md --- CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 536395f..df7736c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,10 @@ Change Log ========== +### 3.?.? - 2019-??-?? + +* Added back `inputUpAxis` and `outputUpAxis`. [#211](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/211) + ### 3.0.4 - 2019-07-22 * No longer printing texture decode warning if the diffuse and alpha textures are the same. [#205](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/205) From db90fff50c28537f09c50badb5f66b6314dc3bd4 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2019 01:08:02 +0000 Subject: [PATCH 14/14] chore(package): update yargs to version 14.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 667da36..f991144 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "jpeg-js": "^0.3.5", "mime": "^2.4.4", "pngjs": "^3.4.0", - "yargs": "^14.0.0" + "yargs": "^14.2.0" }, "devDependencies": { "cloc": "^2.5.0",