diff --git a/lib/loadMtl.js b/lib/loadMtl.js index 2b25371..a7018e9 100644 --- a/lib/loadMtl.js +++ b/lib/loadMtl.js @@ -77,6 +77,21 @@ function loadMtl(mtlPath, options) { materials.push(material); } + /** + * Removes texture options from texture name + * NOTE: assumes no spaces in texture name + * + * @param {String} name + * @returns {String} The clean texture name + */ + function cleanTextureName (name) { + var re = /-(bm|t|s|o|blendu|blendv|boost|mm|texres|clamp|imfchan|type)/; + if (re.test(name)) { + return name.split(/\s+/).pop(); + } + return name; + } + function parseLine(line) { line = line.trim(); if (/^newmtl /i.test(line)) { @@ -125,32 +140,32 @@ function loadMtl(mtlPath, options) { material.alpha = correctAlpha(1.0 - parseFloat(value)); } else if (/^map_Ka /i.test(line)) { if (!defined(overridingAmbientTexture)) { - texturePath = path.resolve(mtlDirectory, line.substring(7).trim()); + texturePath = path.resolve(mtlDirectory, cleanTextureName(line.substring(7).trim())); loadMaterialTexture(material, 'ambientTexture', texturePath, ambientTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); } } else if (/^map_Ke /i.test(line)) { if (!defined(overridingEmissiveTexture)) { - texturePath = path.resolve(mtlDirectory, line.substring(7).trim()); + texturePath = path.resolve(mtlDirectory, cleanTextureName(line.substring(7).trim())); loadMaterialTexture(material, 'emissiveTexture', texturePath, emissiveTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); } } else if (/^map_Kd /i.test(line)) { if (!defined(overridingDiffuseTexture)) { - texturePath = path.resolve(mtlDirectory, line.substring(7).trim()); + texturePath = path.resolve(mtlDirectory, cleanTextureName(line.substring(7).trim())); loadMaterialTexture(material, 'diffuseTexture', texturePath, diffuseTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); } } else if (/^map_Ks /i.test(line)) { if (!defined(overridingSpecularTexture)) { - texturePath = path.resolve(mtlDirectory, line.substring(7).trim()); + texturePath = path.resolve(mtlDirectory, cleanTextureName(line.substring(7).trim())); loadMaterialTexture(material, 'specularTexture', texturePath, specularTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); } } else if (/^map_Ns /i.test(line)) { if (!defined(overridingSpecularShininessTexture)) { - texturePath = path.resolve(mtlDirectory, line.substring(7).trim()); + texturePath = path.resolve(mtlDirectory, cleanTextureName(line.substring(7).trim())); loadMaterialTexture(material, 'specularShininessTexture', texturePath, specularShinessTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); } } else if (/^map_Bump /i.test(line)) { if (!defined(overridingNormalTexture)) { - texturePath = path.resolve(mtlDirectory, line.substring(9).trim()); + texturePath = path.resolve(mtlDirectory, cleanTextureName(line.substring(9).trim())); loadMaterialTexture(material, 'normalTexture', texturePath, normalTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); } } @@ -195,65 +210,11 @@ loadMtl._createMaterial = function(materialOptions, options) { return convertMaterial(combine(materialOptions, new Material()), options); }; -/** - * Parses texture map options like -o, -s, -bm which end up in the texturePath - * - * @param {String} texturePath The original texture path - * @param {Object} textureOptions This object will be filled with the options - * - * @return {String} The fixed texturePath or undefined when there's no texture options - */ -function parseMapOptions (texturePath, textureOptions) { - - var re = /[\\\/]-(bm|t|s|o|blendu|blendv|boost|mm|texres|clamp|imfchan|type)/; - - if (!re.test(texturePath)) { - return; - } - - if (re.test('/'+path.basename(texturePath))) { - // options ended up in filename, eg: map_bump -bm 0.1 foo.jpg - // assume no spaces in texture filename - var parts = path.basename(texturePath).split(/\s+/); - var texture = parts.pop(); - // handle options below - texturePath = path.join(path.dirname(texturePath), parts.join(' '), texture); - } - - var pathParts = texturePath.split(/[\\\/]/); - - if (pathParts.length && pathParts.length > 2) { - var mapOptions = pathParts[pathParts.length - 2].split(/\s+/); - var currPart = null; - - mapOptions.reduce(function (p, part) { - if (re.test('/'+part)) { - currPart = part; - p[part] = []; - } else if (currPart) { - p[currPart].push(part); - } - return p; - }, textureOptions); - - pathParts.splice(pathParts.length - 2, 1); - return path.join.apply(null, pathParts); - } -} - function loadMaterialTexture(material, name, texturePath, textureOptions, mtlDirectory, texturePromiseMap, texturePromises, options) { if (!defined(texturePath)) { return; } - textureOptions = textureOptions || {}; - - var newTexturePath = parseMapOptions(texturePath, textureOptions); - - // TODO: handle texture options - // NOTE: this might not be a good place to do this - texturePath = newTexturePath ? newTexturePath : texturePath; - var texturePromise = texturePromiseMap[texturePath]; if (!defined(texturePromise)) { if (options.secure && outsideDirectory(texturePath, mtlDirectory)) { diff --git a/specs/data/box-texture-options/alpha.png b/specs/data/box-texture-options/alpha.png new file mode 100644 index 0000000..d04eb82 Binary files /dev/null and b/specs/data/box-texture-options/alpha.png differ diff --git a/specs/data/box-texture-options/ambient.gif b/specs/data/box-texture-options/ambient.gif new file mode 100644 index 0000000..1276823 Binary files /dev/null and b/specs/data/box-texture-options/ambient.gif differ diff --git a/specs/data/box-texture-options/box-texture-options.mtl b/specs/data/box-texture-options/box-texture-options.mtl new file mode 100644 index 0000000..76f464a --- /dev/null +++ b/specs/data/box-texture-options/box-texture-options.mtl @@ -0,0 +1,20 @@ +# Blender MTL File: 'box.blend' +# Material Count: 1 + +newmtl Material +Ns 96.078431 +Ka 0.200000 0.200000 0.200000 +Kd 0.640000 0.640000 0.640000 +Ks 0.500000 0.500000 0.500000 +Ke 0.100000 0.100000 0.100000 +Ni 1.000000 +d 0.900000 +Tr 0.100000 +map_Ka -s 1.0 1.0 1.0 -o 0.0 0.0 0.0 ambient.gif +map_Ke -s 1.0 1.0 1.0 -o 0.0 0.0 0.0 emission.jpg +map_Kd -s 1.0 1.0 1.0 -o 0.0 0.0 0.0 diffuse.png +map_Ks -s 1.0 1.0 1.0 -o 0.0 0.0 0.0 specular.jpeg +map_Ns -s 1.0 1.0 1.0 -o 0.0 0.0 0.0 shininess.png +map_Bump -bm 0.2 bump.png +map_d alpha.png +illum 2 diff --git a/specs/data/box-texture-options/box-texture-options.obj b/specs/data/box-texture-options/box-texture-options.obj new file mode 100644 index 0000000..b8d1dde --- /dev/null +++ b/specs/data/box-texture-options/box-texture-options.obj @@ -0,0 +1,46 @@ +# Blender v2.78 (sub 0) OBJ File: 'box.blend' +# www.blender.org +mtllib box-texture-options.mtl +o Cube +v -1.000000 -1.000000 1.000000 +v -1.000000 1.000000 1.000000 +v -1.000000 -1.000000 -1.000000 +v -1.000000 1.000000 -1.000000 +v 1.000000 -1.000000 1.000000 +v 1.000000 1.000000 1.000000 +v 1.000000 -1.000000 -1.000000 +v 1.000000 1.000000 -1.000000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 0.0000 +vt 0.0000 1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 1.0000 +vn 0.0000 -1.0000 0.0000 +vn 0.0000 1.0000 0.0000 +usemtl Material +s off +f 1/1/1 2/2/1 4/3/1 3/4/1 +f 3/5/2 4/6/2 8/7/2 7/8/2 +f 7/9/3 8/10/3 6/11/3 5/12/3 +f 5/13/4 6/14/4 2/15/4 1/16/4 +f 3/5/5 7/17/5 5/18/5 1/16/5 +f 8/19/6 4/6/6 2/15/6 6/20/6 diff --git a/specs/data/box-texture-options/bump.png b/specs/data/box-texture-options/bump.png new file mode 100644 index 0000000..16ec3a9 Binary files /dev/null and b/specs/data/box-texture-options/bump.png differ diff --git a/specs/data/box-texture-options/diffuse.png b/specs/data/box-texture-options/diffuse.png new file mode 100644 index 0000000..8704966 Binary files /dev/null and b/specs/data/box-texture-options/diffuse.png differ diff --git a/specs/data/box-texture-options/emission.jpg b/specs/data/box-texture-options/emission.jpg new file mode 100644 index 0000000..e5c85a9 Binary files /dev/null and b/specs/data/box-texture-options/emission.jpg differ diff --git a/specs/data/box-texture-options/shininess.png b/specs/data/box-texture-options/shininess.png new file mode 100644 index 0000000..bfcf1a2 Binary files /dev/null and b/specs/data/box-texture-options/shininess.png differ diff --git a/specs/data/box-texture-options/specular.jpeg b/specs/data/box-texture-options/specular.jpeg new file mode 100644 index 0000000..661bf98 Binary files /dev/null and b/specs/data/box-texture-options/specular.jpeg differ diff --git a/specs/lib/loadMtlSpec.js b/specs/lib/loadMtlSpec.js index 0a54bf5..059dd45 100644 --- a/specs/lib/loadMtlSpec.js +++ b/specs/lib/loadMtlSpec.js @@ -11,6 +11,7 @@ var clone = Cesium.clone; var coloredMaterialPath = 'specs/data/box/box.mtl'; var texturedMaterialPath = 'specs/data/box-complex-material/box-complex-material.mtl'; +var texturedWithOptionsMaterialPath = 'specs/data/box-texture-options/box-texture-options.mtl'; var multipleMaterialsPath = 'specs/data/box-multiple-materials/box-multiple-materials.mtl'; var externalMaterialPath = 'specs/data/box-external-resources/box-external-resources.mtl'; var transparentMaterialPath = 'specs/data/box-transparent/box-transparent.mtl'; @@ -131,6 +132,28 @@ describe('loadMtl', function() { }), done).toResolve(); }); + it('loads mtl with textures having options', function(done) { + options.metallicRoughness = true; + expect(loadMtl(texturedWithOptionsMaterialPath, options) + .then(function(materials) { + expect(materials.length).toBe(1); + var material = materials[0]; + var pbr = material.pbrMetallicRoughness; + expect(pbr.baseColorTexture).toBeDefined(); + expect(pbr.metallicRoughnessTexture).toBeDefined(); + expect(pbr.baseColorFactor).toEqual([1.0, 1.0, 1.0, 0.9]); + expect(pbr.metallicFactor).toBe(1.0); + expect(pbr.roughnessFactor).toBe(1.0); + expect(material.name).toBe('Material'); + expect(material.emissiveTexture).toBeDefined(); + expect(material.normalTexture).toBeDefined(); + expect(material.occlusionTexture).toBeDefined(); + expect(material.emissiveFactor).toEqual([1.0, 1.0, 1.0]); + expect(material.alphaMode).toBe('BLEND'); + expect(material.doubleSided).toBe(true); + }), done).toResolve(); + }); + it('loads mtl with multiple materials', function(done) { options.metallicRoughness = true; expect(loadMtl(multipleMaterialsPath, options)