diff --git a/CHANGES.md b/CHANGES.md index a4b64e7..b62fd97 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,10 @@ Change Log ========== +### 2.2.0 ??? + +* Fixed handling of `usemtl` when appearing before an `o` or `g` token. [#121](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/121) + ### 2.1.0 2017-12-28 * Fixed loading faces that contain less than 3 vertices. [#120](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/120) diff --git a/lib/loadObj.js b/lib/loadObj.js index 70f8380..1ba9842 100644 --- a/lib/loadObj.js +++ b/lib/loadObj.js @@ -71,6 +71,7 @@ function loadObj(objPath, options) { var node; var mesh; var primitive; + var activeMaterial; // All nodes seen in the obj var nodes = []; @@ -120,12 +121,15 @@ function loadObj(objPath, options) { function addPrimitive() { primitive = new Primitive(); + primitive.material = activeMaterial; mesh.primitives.push(primitive); } function useMaterial(name) { - // Look to see if this material has already been used by a primitive in the mesh var material = getName(name); + activeMaterial = material; + + // Look to see if this material has already been used by a primitive in the mesh var primitives = mesh.primitives; var primitivesLength = primitives.length; for (var i = 0; i < primitivesLength; ++i) { @@ -136,7 +140,6 @@ function loadObj(objPath, options) { } // Add a new primitive with this material addPrimitive(); - primitive.material = getName(name); } function getOffset(a, attributeData, components) { @@ -533,6 +536,12 @@ function finishLoading(nodes, mtlPaths, objPath, options) { function loadMtls(mtlPaths, objPath, options) { var objDirectory = path.dirname(objPath); var materials = []; + + // Remove duplicates + mtlPaths = mtlPaths.filter(function(value, index, self) { + return self.indexOf(value) === index; + }); + return Promise.map(mtlPaths, function(mtlPath) { mtlPath = path.resolve(objDirectory, mtlPath); var shallowPath = path.resolve(path.join(objDirectory, path.basename(mtlPath))); diff --git a/specs/data/box-objects-groups-materials-2/box-objects-groups-materials-2.mtl b/specs/data/box-objects-groups-materials-2/box-objects-groups-materials-2.mtl new file mode 100644 index 0000000..2f9b11a --- /dev/null +++ b/specs/data/box-objects-groups-materials-2/box-objects-groups-materials-2.mtl @@ -0,0 +1,32 @@ +# Blender MTL File: 'box-objects.blend' +# Material Count: 3 + +newmtl Blue +Ns 96.078431 +Ka 0.000000 0.000000 0.000000 +Kd 0.000000 0.000000 0.640000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.000000 +d 1.000000 +illum 2 + +newmtl Green +Ns 96.078431 +Ka 0.000000 0.000000 0.000000 +Kd 0.000000 0.640000 0.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.000000 +d 1.000000 +illum 2 + +newmtl Red +Ns 96.078431 +Ka 0.000000 0.000000 0.000000 +Kd 0.640000 0.000000 0.000000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.000000 +d 1.000000 +illum 2 diff --git a/specs/data/box-objects-groups-materials-2/box-objects-groups-materials-2.obj b/specs/data/box-objects-groups-materials-2/box-objects-groups-materials-2.obj new file mode 100644 index 0000000..aed6a84 --- /dev/null +++ b/specs/data/box-objects-groups-materials-2/box-objects-groups-materials-2.obj @@ -0,0 +1,133 @@ +# Blender v2.78 (sub 0) OBJ File: 'box-objects.blend' +# www.blender.org +mtllib box-objects-groups-materials-2.mtl +usemtl Blue +o Cube +v -1.000000 -1.000000 -4.000000 +v -1.000000 1.000000 -4.000000 +v -1.000000 -1.000000 -6.000000 +v -1.000000 1.000000 -6.000000 +v 1.000000 -1.000000 -4.000000 +v 1.000000 1.000000 -4.000000 +v 1.000000 -1.000000 -6.000000 +v 1.000000 1.000000 -6.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 +g Blue +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 +usemtl Green +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 +v 4.000000 -1.000000 1.000000 +v 4.000000 1.000000 1.000000 +v 4.000000 -1.000000 -1.000000 +v 4.000000 1.000000 -1.000000 +v 6.000000 -1.000000 1.000000 +v 6.000000 1.000000 1.000000 +v 6.000000 -1.000000 -1.000000 +v 6.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 Green +g Green +f 9/21/7 10/22/7 12/23/7 11/24/7 +f 11/25/8 12/26/8 16/27/8 15/28/8 +f 15/29/9 16/30/9 14/31/9 13/32/9 +usemtl Red +f 13/33/10 14/34/10 10/35/10 9/36/10 +f 11/25/11 15/37/11 13/38/11 9/36/11 +f 16/39/12 12/26/12 10/35/12 14/40/12 +usemtl Red +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 +g Red +f 21/53/16 22/54/16 18/55/16 17/56/16 +f 19/45/17 23/57/17 21/58/17 17/56/17 +f 24/59/18 20/46/18 18/55/18 22/60/18 +usemtl Blue +f 17/41/13 18/42/13 20/43/13 19/44/13 +f 19/45/14 20/46/14 24/47/14 23/48/14 +f 23/49/15 24/50/15 22/51/15 21/52/15 diff --git a/specs/lib/loadObjSpec.js b/specs/lib/loadObjSpec.js index ea6004b..572ae3d 100644 --- a/specs/lib/loadObjSpec.js +++ b/specs/lib/loadObjSpec.js @@ -16,6 +16,8 @@ var objTrianglesPath = 'specs/data/box-triangles/box-triangles.obj'; var objObjectsPath = 'specs/data/box-objects/box-objects.obj'; var objGroupsPath = 'specs/data/box-groups/box-groups.obj'; var objObjectsGroupsPath = 'specs/data/box-objects-groups/box-objects-groups.obj'; +var objObjectsGroupsMaterialsPath = 'specs/data/box-objects-groups-materials/box-objects-groups-materials.obj'; +var objObjectsGroupsMaterialsPath2 = 'specs/data/box-objects-groups-materials-2/box-objects-groups-materials-2.obj'; var objUsemtlPath = 'specs/data/box-usemtl/box-usemtl.obj'; var objNoMaterialsPath = 'specs/data/box-no-materials/box-no-materials.obj'; var objMultipleMaterialsPath = 'specs/data/box-multiple-materials/box-multiple-materials.obj'; @@ -194,6 +196,41 @@ describe('loadObj', function() { }), done).toResolve(); }); + function loadsObjWithObjectsGroupsAndMaterials(data) { + var nodes = data.nodes; + expect(nodes.length).toBe(1); + expect(nodes[0].name).toBe('Cube'); + var meshes = getMeshes(data); + expect(meshes.length).toBe(3); + expect(meshes[0].name).toBe('Blue'); + expect(meshes[1].name).toBe('Green'); + expect(meshes[2].name).toBe('Red'); + var primitives = getPrimitives(data); + expect(primitives.length).toBe(6); + expect(primitives[0].material).toBe('Blue'); + expect(primitives[1].material).toBe('Green'); + expect(primitives[2].material).toBe('Green'); + expect(primitives[3].material).toBe('Red'); + expect(primitives[4].material).toBe('Red'); + expect(primitives[5].material).toBe('Blue'); + } + + it('loads obj with objects, groups, and materials', function(done) { + expect(loadObj(objObjectsGroupsMaterialsPath, options) + .then(function(data) { + loadsObjWithObjectsGroupsAndMaterials(data); + }), done).toResolve(); + }); + + it('loads obj with objects, groups, and materials (2)', function(done) { + // The usemtl lines are placed in an unordered fashion but + // should produce the same result as the previous test + expect(loadObj(objObjectsGroupsMaterialsPath2, options) + .then(function(data) { + loadsObjWithObjectsGroupsAndMaterials(data); + }), done).toResolve(); + }); + it('loads obj with concave face containing 5 vertices', function(done) { expect(loadObj(objConcavePath, options) .then(function(data) {