Merge pull request #218 from AnalyticalGraphicsInc/missing-attributes

Fix parsing faces that reference non-existing attributes
This commit is contained in:
Sean Lilley 2019-10-29 13:44:25 -04:00 committed by GitHub
commit dcaba3453a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 189 additions and 4 deletions

View File

@ -4,6 +4,7 @@ Change Log
### 3.?.? - 2019-??-?? ### 3.?.? - 2019-??-??
* Added back `inputUpAxis` and `outputUpAxis`. [#211](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/211) * Added back `inputUpAxis` and `outputUpAxis`. [#211](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/211)
* Fixed parsing faces that reference non-existing attributes. [#218](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/218)
### 3.0.4 - 2019-07-22 ### 3.0.4 - 2019-07-22

View File

@ -195,7 +195,10 @@ function loadObj(objPath, options) {
function createVertex(p, u, n) { function createVertex(p, u, n) {
// Positions // Positions
if (defined(p)) { if (defined(p) && (globalPositions.length > 0)) {
if (p * 3 >= globalPositions.length) {
throw new RuntimeError(`Position index ${p} is out of bounds`);
}
const px = globalPositions.get(p * 3); const px = globalPositions.get(p * 3);
const py = globalPositions.get(p * 3 + 1); const py = globalPositions.get(p * 3 + 1);
const pz = globalPositions.get(p * 3 + 2); const pz = globalPositions.get(p * 3 + 2);
@ -205,7 +208,10 @@ function loadObj(objPath, options) {
} }
// Normals // Normals
if (defined(n)) { if (defined(n) && (globalNormals.length > 0)) {
if (n * 3 >= globalNormals.length) {
throw new RuntimeError(`Normal index ${n} is out of bounds`);
}
const nx = globalNormals.get(n * 3); const nx = globalNormals.get(n * 3);
const ny = globalNormals.get(n * 3 + 1); const ny = globalNormals.get(n * 3 + 1);
const nz = globalNormals.get(n * 3 + 2); const nz = globalNormals.get(n * 3 + 2);
@ -215,7 +221,10 @@ function loadObj(objPath, options) {
} }
// UVs // UVs
if (defined(u)) { if (defined(u) && (globalUvs.length > 0)) {
if (u * 2 >= globalUvs.length) {
throw new RuntimeError(`UV index ${u} is out of bounds`);
}
const ux = globalUvs.get(u * 2); const ux = globalUvs.get(u * 2);
const uy = globalUvs.get(u * 2 + 1); const uy = globalUvs.get(u * 2 + 1);
primitive.uvs.push(ux); primitive.uvs.push(ux);

View File

@ -23,6 +23,15 @@ function readLines(path, callback) {
const lineReader = readline.createInterface({ const lineReader = readline.createInterface({
input : stream input : stream
}); });
lineReader.on('line', callback);
const callbackWrapper = function(line) {
try {
callback(line);
} catch (error) {
reject(error);
}
};
lineReader.on('line', callbackWrapper);
}); });
} }

View File

@ -0,0 +1,36 @@
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.000000 0.000000 1.000000
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

@ -0,0 +1,34 @@
o Cube
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
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

@ -0,0 +1,22 @@
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
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
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

@ -0,0 +1,12 @@
# Blender MTL File: 'box.blend'
# Material Count: 1
newmtl Material
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2

View File

@ -0,0 +1,20 @@
# Blender v2.78 (sub 0) OBJ File: 'box.blend'
# www.blender.org
mtllib box-missing-attributes.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
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

View File

@ -41,6 +41,10 @@ const objInvalidContentsPath = 'specs/data/box/box.mtl';
const objConcavePath = 'specs/data/concave/concave.obj'; const objConcavePath = 'specs/data/concave/concave.obj';
const objUnnormalizedPath = 'specs/data/box-unnormalized/box-unnormalized.obj'; const objUnnormalizedPath = 'specs/data/box-unnormalized/box-unnormalized.obj';
const objMixedAttributesPath = 'specs/data/box-mixed-attributes/box-mixed-attributes.obj'; const objMixedAttributesPath = 'specs/data/box-mixed-attributes/box-mixed-attributes.obj';
const objMissingAttributesPath = 'specs/data/box-missing-attributes/box-missing-attributes.obj';
const objIncompletePositionsPath = 'specs/data/box-incomplete-attributes/box-incomplete-positions.obj';
const objIncompleteNormalsPath = 'specs/data/box-incomplete-attributes/box-incomplete-normals.obj';
const objIncompleteUvsPath = 'specs/data/box-incomplete-attributes/box-incomplete-uvs.obj';
const objInvalidPath = 'invalid.obj'; const objInvalidPath = 'invalid.obj';
function getMeshes(data) { function getMeshes(data) {
@ -496,6 +500,44 @@ describe('loadObj', () => {
} }
}); });
it('ignores missing normals and uvs', async () => {
const data = await loadObj(objMissingAttributesPath, options);
const primitive = getPrimitives(data)[0];
expect(primitive.positions.length).toBeGreaterThan(0);
expect(primitive.normals.length).toBe(0);
expect(primitive.uvs.length).toBe(0);
});
it('throws when position index is out of bounds', async () => {
let thrownError;
try {
await loadObj(objIncompletePositionsPath, options);
} catch (e) {
thrownError = e;
}
expect(thrownError).toEqual(new RuntimeError('Position index 1 is out of bounds'));
});
it('throws when normal index is out of bounds', async () => {
let thrownError;
try {
await loadObj(objIncompleteNormalsPath, options);
} catch (e) {
thrownError = e;
}
expect(thrownError).toEqual(new RuntimeError('Normal index 1 is out of bounds'));
});
it('throws when uv index is out of bounds', async () => {
let thrownError;
try {
await loadObj(objIncompleteUvsPath, options);
} catch (e) {
thrownError = e;
}
expect(thrownError).toEqual(new RuntimeError('UV index 1 is out of bounds'));
});
it('throws when file has invalid contents', async () => { it('throws when file has invalid contents', async () => {
let thrownError; let thrownError;
try { try {