diff --git a/bin/obj2gltf.js b/bin/obj2gltf.js index 27347e7..74d9654 100644 --- a/bin/obj2gltf.js +++ b/bin/obj2gltf.js @@ -20,14 +20,16 @@ if (process.argv.length < 3 || defined(argv.h) || defined(argv.help)) { console.log(' -o, --output Directory or filename for the exported glTF file'); console.log(' -b, --binary Output binary glTF'); console.log(' -c --combine Combine glTF resources into a single file'); + console.log(' -t --technique Shading technique. Possible values are lambert, phong, blinn, constant'); console.log(' -h, --help Display this help'); process.exit(0); } var objFile = defaultValue(argv._[0], defaultValue(argv.i, argv.input)); -var outputPath = defaultValue(defaultValue(argv.o, argv.output)); +var outputPath = defaultValue(argv._[1], defaultValue(argv.o, argv.output)); var binary = defaultValue(defaultValue(argv.b, argv.binary), false); var combine = defaultValue(defaultValue(argv.c, argv.combine), false); +var technique = defaultValue(argv.t, argv.technique); if (!defined(objFile)) { console.error('-i or --input argument is required. See --help for details.'); @@ -38,6 +40,13 @@ if (!defined(outputPath)) { outputPath = path.dirname(objFile); } +if (defined(technique)) { + technique = technique.toUpperCase(); + if ((technique !== 'LAMBERT') && (technique !== 'PHONG') && (technique !== 'BLINN') && (technique !== 'CONSTANT')) { + console.log('Unrecognized technique \'' + technique + '\'. Using default instead.'); + } +} + var inputPath = path.dirname(objFile); var modelName = path.basename(objFile, '.obj'); @@ -53,7 +62,7 @@ fs.mkdir(outputPath, function(){ parseObj(objFile, inputPath, function(data) { console.timeEnd('Parse Obj'); console.time('Create glTF'); - createGltf(data, modelName, inputPath, outputPath, binary, combine, function() { + createGltf(data, modelName, inputPath, outputPath, binary, combine, technique, function() { console.timeEnd('Create glTF'); console.timeEnd('Total'); }); diff --git a/lib/gltf.js b/lib/gltf.js index aeae108..beace44 100644 --- a/lib/gltf.js +++ b/lib/gltf.js @@ -15,16 +15,21 @@ module.exports = createGltf; function getImages(inputPath, outputPath, combine, materials, done) { var images = []; + for (var name in materials) { if (materials.hasOwnProperty(name)) { var material = materials[name]; - for (var property in material) { - if (material.hasOwnProperty(property)) { - var image = material[property]; - if (typeof image === 'string') { - images.push(image); - } - } + if (defined(material.ambientColorMap) && (images.indexOf(material.ambientColorMap) === -1)) { + images.push(material.ambientColorMap); + } + if (defined(material.diffuseColorMap) && (images.indexOf(material.diffuseColorMap) === -1)) { + images.push(material.diffuseColorMap); + } + if (defined(material.emissionColorMap) && (images.indexOf(material.emissionColorMap) === -1)) { + images.push(material.emissionColorMap); + } + if (defined(material.specularColorMap) && (images.indexOf(material.specularColorMap) === -1)) { + images.push(material.specularColorMap); } } } @@ -47,12 +52,16 @@ function getImages(inputPath, outputPath, combine, materials, done) { uri : uri }; - fsExtra.copy(imagePath, copyPath, function (err) { - if (err) { - throw err; - } + if (combine) { callback(); - }); + } else { + fsExtra.copy(imagePath, copyPath, {clobber : true}, function (err) { + if (err) { + throw err; + } + callback(); + }); + } }); }, function (err) { if (err) { @@ -62,7 +71,7 @@ function getImages(inputPath, outputPath, combine, materials, done) { }); } -function createGltf(data, modelName, inputPath, outputPath, binary, combine, done) { +function createGltf(data, modelName, inputPath, outputPath, binary, combine, technique, done) { var vertexCount = data.vertexCount; var vertexArray = data.vertexArray; var positionMin = data.positionMin; @@ -305,44 +314,40 @@ function createGltf(data, modelName, inputPath, outputPath, binary, combine, don }); } - function addTexture(name) { - var imageId = getImageId(name); - var textureId = getTextureId(name); + for (name in images) { + if (images.hasOwnProperty(name)) { + var image = images[name]; + var imageId = getImageId(name); + var textureId = getTextureId(name); + var format; + var channels = image.channels; + switch (channels) { + case 1: + format = WebGLConstants.ALPHA; + break; + case 2: + format = WebGLConstants.LUMINANCE_ALPHA; + break; + case 3: + format = WebGLConstants.RGB; + break; + case 4: + format = WebGLConstants.RGBA; + break; + } - // Don't add the texture twice - if (defined(gltf.images[imageId])) { - return; + gltf.images[imageId] = { + uri : image.uri + }; + gltf.textures[textureId] = { + format : format, + internalFormat : format, + sampler : samplerId, + source : imageId, + target : WebGLConstants.TEXTURE_2D, + type : WebGLConstants.UNSIGNED_BYTE + }; } - - var image = images[name]; - var format; - var channels = image.channels; - switch (channels) { - case 1: - format = WebGLConstants.ALPHA; - break; - case 2: - format = WebGLConstants.LUMINANCE_ALPHA; - break; - case 3: - format = WebGLConstants.RGB; - break; - case 4: - format = WebGLConstants.RGBA; - break; - } - - gltf.images[imageId] = { - uri : image.uri - }; - gltf.textures[textureId] = { - format : format, - internalFormat : format, - sampler : samplerId, - source : imageId, - target : WebGLConstants.TEXTURE_2D, - type : WebGLConstants.UNSIGNED_BYTE - }; } for (i = 0; i < primitivesLength; ++i) { @@ -350,52 +355,41 @@ function createGltf(data, modelName, inputPath, outputPath, binary, combine, don var material = materials[materialName]; var materialId = getMaterialId(materialName); - // Get specular color as combination of specular color and intensity - var specularColor = material.specularColor; - var specularIntensity = material.specularIntensity; - if (defined(specularColor)) { - specularIntensity = defaultValue(specularIntensity, 1.0); - specularColor[0] *= specularIntensity; - specularColor[1] *= specularIntensity; - specularColor[2] *= specularIntensity; - } else if(defined(specularIntensity)){ - specularColor = [specularIntensity, specularIntensity, specularIntensity, 1]; + // Get shading technique + var shadingTechnique = technique; + var specularColor = defaultValue(material.specularColor, [0, 0, 0, 1]); + var specularShininess = material.specularShininess; + var hasSpecularColor = (specularColor[0] > 0) || (specularColor[1] > 0) || (specularColor[2] > 0); + var hasSpecularColorMap = defined(material.specularColorMap); + if (defined(shadingTechnique)) { + if ((shadingTechnique === 'PHONG') || (shadingTechnique === 'BLINN')) { + if (!defined(specularShininess)) { + specularShininess = 10.0; + } + if (!hasSpecularColor) { + specularColor[0] = specularColor[1] = specularColor[2] = 0.5; + } + } } else { - specularColor = [0, 0, 0, 1]; - } - - var specularMap = defaultValue(material.specularColorMap, material.specularIntensityMap); - var shadingTechnique = 'PHONG'; // or 'BLINN' - if (!defined(specularMap) && (specularColor[0] === 0) && (specularColor[1] === 0) && (specularColor[2] === 0)) { - shadingTechnique = 'LAMBERT'; - } - - if (defined(material.ambientColorMap)) { - addTexture(material.ambientColorMap); - } - if (defined(material.diffuseColorMap)) { - addTexture(material.diffuseColorMap); - } - if (defined(material.emissionColorMap)) { - addTexture(material.emissionColorMap); - } - if (defined(specularMap)) { - addTexture(specularMap); + shadingTechnique = 'BLINN'; + if (!hasSpecularColorMap && !hasSpecularColor) { + shadingTechnique = 'LAMBERT'; + } } var values = { ambient : defaultValue(defaultValue(getTextureId(material.ambientColorMap), material.ambientColor), [0, 0, 0, 1]), diffuse : defaultValue(defaultValue(getTextureId(material.diffuseColorMap), material.diffuseColor), [0, 0, 0, 1]), emission : defaultValue(defaultValue(getTextureId(material.emissionColorMap), material.emissionColor), [0, 0, 0, 1]), - specular : defaultValue(getTextureId(specularMap), specularColor), - shininess : defaultValue(material.specularShininess, 0.0), + specular : defaultValue(getTextureId(material.specularColorMap), specularColor), + shininess : defaultValue(specularShininess, 0.0), transparency : defaultValue(material.alpha, 1.0) }; // If an image is transparent, set transparency to 0.99 to force alpha path var diffuseColorMap = material.diffuseColorMap; if (defined(diffuseColorMap) && images[diffuseColorMap].transparent) { - values.transparency = 0.99 * values.transparency; + values.transparency = 0.99 * (values.transparency || 1.0); } gltf.materials[materialId] = { diff --git a/lib/modelMaterialsCommon.js b/lib/modelMaterialsCommon.js index d1b78bd..bdf084f 100644 --- a/lib/modelMaterialsCommon.js +++ b/lib/modelMaterialsCommon.js @@ -479,7 +479,7 @@ function generateTechnique(gltf, khrMaterialsCommon, attributes, lightParameters if (hasSpecular) { if (techniqueParameters.specular.type === WebGLConstants.SAMPLER_2D) { - fragmentShader += ' vec3 specular = texture2D(u_specular, ' + v_texcoord + ');\n'; + fragmentShader += ' vec3 specular = texture2D(u_specular, ' + v_texcoord + ').rgb;\n'; } else { fragmentShader += ' vec3 specular = u_specular.rgb;\n'; @@ -747,4 +747,4 @@ function modelMaterialsCommon(gltf) { } return gltf; -}; +} diff --git a/lib/mtl.js b/lib/mtl.js index 9d4837c..a9c7fce 100644 --- a/lib/mtl.js +++ b/lib/mtl.js @@ -13,14 +13,12 @@ function createMaterial() { diffuseColor : undefined, // Kd specularColor : undefined, // Ks specularShininess : undefined, // Ns - specularIntensity : undefined, // Ni alpha : undefined, // d ambientColorMap : undefined, // map_Ka emissionColorMap : undefined, // map_Ke diffuseColorMap : undefined, // map_Kd specularColorMap : undefined, // map_Ks specularShininessMap : undefined, // map_Ns - specularIntensityMap : undefined, // map_Ni normalMap : undefined, // map_Bump alphaMap : undefined // map_d }; @@ -88,9 +86,6 @@ function parse(mtlPath, done) { } else if (/^Ns /i.test(line)) { value = line.substring(3).trim(); material.specularShininess = parseFloat(value); - } else if (/^Ni /i.test(line)) { - value = line.substring(3).trim(); - material.specularIntensity = parseFloat(value); } else if (/^d /i.test(line)) { value = line.substring(2).trim(); material.alpha = parseFloat(value); @@ -104,8 +99,6 @@ function parse(mtlPath, done) { material.specularColorMap = line.substring(7).trim(); } else if (/^map_Ns /i.test(line)) { material.specularShininessMap = line.substring(7).trim(); - } else if (/^map_Ni /i.test(line)) { - material.specularIntensityMap = line.substring(7).trim(); } else if (/^map_Bump /i.test(line)) { material.normalMap = line.substring(9).trim(); } else if (/^map_d /i.test(line)) { diff --git a/lib/obj.js b/lib/obj.js index f8179f4..c840455 100644 --- a/lib/obj.js +++ b/lib/obj.js @@ -55,7 +55,7 @@ function parseObj(objFile, inputPath, done) { var hasUVs = /^vt/gm.test(contents); if (!hasPositions) { - console.log('Could not process obj file, no positions.') + console.log('Could not process obj file, no positions.'); } // Map material to index array