diff --git a/lib/loadObj.js b/lib/loadObj.js index 1ba9842..015ffef 100644 --- a/lib/loadObj.js +++ b/lib/loadObj.js @@ -447,9 +447,15 @@ function loadObj(objPath, options) { positions.push(parseFloat(result[2])); positions.push(parseFloat(result[3])); } else if ((result = normalPattern.exec(line) ) !== null) { - normals.push(parseFloat(result[1])); - normals.push(parseFloat(result[2])); - normals.push(parseFloat(result[3])); + var normal = Cartesian3.fromElements(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3]), scratchNormal); + if (Cartesian3.equals(normal, Cartesian3.ZERO)) { + Cartesian3.clone(Cartesian3.UNIT_Z, normal); + } else { + Cartesian3.normalize(normal, normal); + } + normals.push(normal.x); + normals.push(normal.y); + normals.push(normal.z); } else if ((result = uvPattern.exec(line)) !== null) { uvs.push(parseFloat(result[1])); uvs.push(1.0 - parseFloat(result[2])); // Flip y so 0.0 is the bottom of the image diff --git a/specs/data/box-unnormalized/box-unnormalized.mtl b/specs/data/box-unnormalized/box-unnormalized.mtl new file mode 100644 index 0000000..4f8d129 --- /dev/null +++ b/specs/data/box-unnormalized/box-unnormalized.mtl @@ -0,0 +1,12 @@ +# Blender MTL File: 'None' +# Material Count: 1 + +newmtl Material +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-unnormalized/box-unnormalized.obj b/specs/data/box-unnormalized/box-unnormalized.obj new file mode 100644 index 0000000..f52251e --- /dev/null +++ b/specs/data/box-unnormalized/box-unnormalized.obj @@ -0,0 +1,46 @@ +# Blender v2.78 (sub 0) OBJ File: '' +# www.blender.org +mtllib box-unnormalized.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 0.0000 0.0000 0.0000 +vn 0.0000 0.0000 0.5 +vn 1.0000 0.1000 0.0000 +vn 0.0000 0.0000 -0.9 +vn 0.0000 1.0000 0.0000 +vn 10.0000 -10.0000 5.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/lib/loadObjSpec.js b/specs/lib/loadObjSpec.js index 572ae3d..1a4c397 100644 --- a/specs/lib/loadObjSpec.js +++ b/specs/lib/loadObjSpec.js @@ -4,6 +4,8 @@ var Promise = require('bluebird'); var loadObj = require('../../lib/loadObj'); var obj2gltf = require('../../lib/obj2gltf'); +var Cartesian3 = Cesium.Cartesian3; +var CesiumMath = Cesium.Math; var clone = Cesium.clone; var RuntimeError = Cesium.RuntimeError; @@ -33,6 +35,7 @@ var objMissingTexturePath = 'specs/data/box-missing-texture/box-missing-texture. var objSubdirectoriesPath = 'specs/data/box-subdirectories/box-textured.obj'; var objInvalidContentsPath = 'specs/data/box/box.mtl'; var objConcavePath = 'specs/data/concave/concave.obj'; +var objUnnormalizedPath = 'specs/data/box-unnormalized/box-unnormalized.obj'; var objInvalidPath = 'invalid.obj'; function getMeshes(data) { @@ -107,6 +110,23 @@ describe('loadObj', function() { }), done).toResolve(); }); + it('normalizes normals', function(done) { + expect(loadObj(objUnnormalizedPath, options) + .then(function(data) { + var scratchNormal = new Cesium.Cartesian3(); + var mesh = getMeshes(data)[0]; + var normals = mesh.normals; + var normalsLength = normals.length / 3; + for (var i = 0; i < normalsLength; ++i) { + var normalX = normals.get(i * 3); + var normalY = normals.get(i * 3 + 1); + var normalZ = normals.get(i * 3 + 2); + var normal = Cartesian3.fromElements(normalX, normalY, normalZ, scratchNormal); + expect(Cartesian3.magnitude(normal)).toEqualEpsilon(1.0, CesiumMath.EPSILON5); + } + }), done).toResolve(); + }); + it('loads obj with uvs', function(done) { expect(loadObj(objUvsPath, options) .then(function(data) {