Fix parsing mtl with newmtl without a name

This commit is contained in:
Sean Lilley 2019-01-03 09:29:02 -05:00
parent b458856904
commit ed54251fec
5 changed files with 98 additions and 2 deletions

View File

@ -332,7 +332,7 @@ function loadObj(objPath, options) {
} else if (/^g\s/i.test(line)) { } else if (/^g\s/i.test(line)) {
var groupName = line.substring(2).trim(); var groupName = line.substring(2).trim();
addMesh(groupName); addMesh(groupName);
} else if (/^usemtl\s/i.test(line)) { } else if (/^usemtl/i.test(line)) {
var materialName = line.substring(7).trim(); var materialName = line.substring(7).trim();
useMaterial(materialName); useMaterial(materialName);
} else if (/^mtllib/i.test(line)) { } else if (/^mtllib/i.test(line)) {
@ -430,6 +430,7 @@ function finishLoading(nodes, mtlPaths, objPath, usesMaterials, options) {
if (materials.length > 0 && !usesMaterials) { if (materials.length > 0 && !usesMaterials) {
assignDefaultMaterial(nodes, materials, usesMaterials); assignDefaultMaterial(nodes, materials, usesMaterials);
} }
assignUnnamedMaterial(nodes, materials);
return { return {
nodes : nodes, nodes : nodes,
materials : materials, 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) { function removeEmptyMeshes(meshes) {
return meshes.filter(function(mesh) { return meshes.filter(function(mesh) {
// Remove empty primitives // Remove empty primitives

View File

@ -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

View File

@ -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

View File

@ -28,6 +28,7 @@ var objMtllibPath = 'specs/data/box-mtllib/box-mtllib.obj';
var objMtllibSpacesPath = 'specs/data/box-mtllib-spaces/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 objMissingMtllibPath = 'specs/data/box-missing-mtllib/box-missing-mtllib.obj';
var objMissingUsemtlPath = 'specs/data/box-missing-usemtl/box-missing-usemtl.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 objExternalResourcesPath = 'specs/data/box-external-resources/box-external-resources.obj';
var objResourcesInRootPath = 'specs/data/box-resources-in-root/box-resources-in-root.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'; var objExternalResourcesInRootPath = 'specs/data/box-external-resources-in-root/box-external-resources-in-root.obj';
@ -399,6 +400,14 @@ describe('loadObj', function() {
}), done).toResolve(); }), 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) { it('loads .mtl outside of the obj directory', function(done) {
expect(loadObj(objExternalResourcesPath, options) expect(loadObj(objExternalResourcesPath, options)
.then(function(data) { .then(function(data) {