diff --git a/lib/loadMtl.js b/lib/loadMtl.js index 9d10240d..b2d804a4 100644 --- a/lib/loadMtl.js +++ b/lib/loadMtl.js @@ -93,7 +93,7 @@ function loadMtl(mtlPath, options) { function parseLine(line) { line = line.trim(); - if (/^newmtl /i.test(line)) { + if (/^newmtl/i.test(line)) { var name = line.substring(7).trim(); createMaterial(name); } else if (/^Ka /i.test(line)) { diff --git a/lib/loadObj.js b/lib/loadObj.js index 1103e888..74786896 100644 --- a/lib/loadObj.js +++ b/lib/loadObj.js @@ -332,7 +332,7 @@ function loadObj(objPath, options) { } else if (/^g\s/i.test(line)) { var groupName = line.substring(2).trim(); addMesh(groupName); - } else if (/^usemtl\s/i.test(line)) { + } else if (/^usemtl/i.test(line)) { var materialName = line.substring(7).trim(); useMaterial(materialName); } else if (/^mtllib/i.test(line)) { @@ -430,6 +430,7 @@ function finishLoading(nodes, mtlPaths, objPath, usesMaterials, options) { if (materials.length > 0 && !usesMaterials) { assignDefaultMaterial(nodes, materials, usesMaterials); } + assignUnnamedMaterial(nodes, materials); return { nodes : nodes, materials : materials, @@ -505,6 +506,34 @@ function assignDefaultMaterial(nodes, materials) { } } +function assignUnnamedMaterial(nodes, materials) { + // If there is a material that doesn't have a name, assign that + // material to any primitives whose material is undefined. + var unnamedMaterial = materials.find(function(material) { + return material.name.length === 0; + }); + + if (!defined(unnamedMaterial)) { + return; + } + + var nodesLength = nodes.length; + for (var i = 0; i < nodesLength; ++i) { + var meshes = nodes[i].meshes; + var meshesLength = meshes.length; + for (var j = 0; j < meshesLength; ++j) { + var primitives = meshes[j].primitives; + var primitivesLength = primitives.length; + for (var k = 0; k < primitivesLength; ++k) { + var primitive = primitives[k]; + if (!defined(primitive.material)) { + primitive.material = unnamedMaterial.name; + } + } + } + } +} + function removeEmptyMeshes(meshes) { return meshes.filter(function(mesh) { // Remove empty primitives diff --git a/specs/data/box-unnamed-material/box-unnamed-material.mtl b/specs/data/box-unnamed-material/box-unnamed-material.mtl new file mode 100644 index 00000000..c9c9f02b --- /dev/null +++ b/specs/data/box-unnamed-material/box-unnamed-material.mtl @@ -0,0 +1,12 @@ +# Blender MTL File: 'None' +# Material Count: 1 + +newmtl +Ns 96.078431 +Ka 0.100000 0.000000 0.000000 +Kd 0.640000 0.640000 0.640000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.100000 +Ni 1.000000 +d 1.000000 +illum 2 diff --git a/specs/data/box-unnamed-material/box-unnamed-material.obj b/specs/data/box-unnamed-material/box-unnamed-material.obj new file mode 100644 index 00000000..1a70a530 --- /dev/null +++ b/specs/data/box-unnamed-material/box-unnamed-material.obj @@ -0,0 +1,46 @@ +# Blender v2.78 (sub 0) OBJ File: '' +# www.blender.org +mtllib box-unnamed-material.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 +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/lib/loadObjSpec.js b/specs/lib/loadObjSpec.js index cd0b7cd3..64e346db 100644 --- a/specs/lib/loadObjSpec.js +++ b/specs/lib/loadObjSpec.js @@ -28,6 +28,7 @@ var objMtllibPath = 'specs/data/box-mtllib/box-mtllib.obj'; var objMtllibSpacesPath = 'specs/data/box-mtllib-spaces/box mtllib.obj'; var objMissingMtllibPath = 'specs/data/box-missing-mtllib/box-missing-mtllib.obj'; var objMissingUsemtlPath = 'specs/data/box-missing-usemtl/box-missing-usemtl.obj'; +var objUnnamedMaterialPath = 'specs/data/box-unnamed-material/box-unnamed-material.obj'; var objExternalResourcesPath = 'specs/data/box-external-resources/box-external-resources.obj'; var objResourcesInRootPath = 'specs/data/box-resources-in-root/box-resources-in-root.obj'; var objExternalResourcesInRootPath = 'specs/data/box-external-resources-in-root/box-external-resources-in-root.obj'; @@ -399,6 +400,14 @@ describe('loadObj', function() { }), done).toResolve(); }); + it('loads obj with unnamed material', function(done) { + expect(loadObj(objUnnamedMaterialPath, options) + .then(function(data) { + expect(data.materials.length).toBe(1); + expect(data.nodes[0].meshes[0].primitives[0].material).toBe(''); + }), done).toResolve(); + }); + it('loads .mtl outside of the obj directory', function(done) { expect(loadObj(objExternalResourcesPath, options) .then(function(data) {