From 31760c34a8b64cc5b82588310844bccc7472efd8 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Wed, 22 Jun 2016 16:16:29 -0400 Subject: [PATCH] Read lines from stream and handle negative indices --- lib/gltf.js | 2 +- lib/obj.js | 152 ++++++++++++++++++++++++++++------------------------ 2 files changed, 84 insertions(+), 70 deletions(-) diff --git a/lib/gltf.js b/lib/gltf.js index bf0bfb6..aadcacf 100644 --- a/lib/gltf.js +++ b/lib/gltf.js @@ -327,7 +327,7 @@ function createGltf(data, inputPath, modelName, done) { } if (bufferSeparate) { - var bufferPath = path.join(path.dirname(inputPath), modelName + '.bin'); + var bufferPath = path.join(inputPath, modelName + '.bin'); fs.writeFile(bufferPath, buffer, function(err) { if (err) { throw err; diff --git a/lib/obj.js b/lib/obj.js index 94a6434..8675013 100644 --- a/lib/obj.js +++ b/lib/obj.js @@ -2,6 +2,7 @@ var async = require('async'); var fs = require('fs-extra'); var path = require('path'); +var readline = require('readline'); var loadImage = require('./image'); var Material = require('./mtl'); var Cesium = require('cesium'); @@ -33,7 +34,7 @@ function processObj(objFile, info, materials, images, done) { var uvs = []; var positionMin = [Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE]; - var positionMax = [Number.MIN_VALUE, Number.MIN_VALUE, Number.MIN_VALUE]; + var positionMax = [-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE]; var hasNormals = info.hasNormals; var hasUVs = info.hasUVs; @@ -67,12 +68,22 @@ function processObj(objFile, info, materials, images, done) { useDefaultMaterial(); } + function getOffset(a, data, components) { + var i = parseInt(a); + if (i < 0) { + // Negative vertex indexes reference the vertices immediately above it + return (data.length / components + i) * components; + } + return (i - 1) * components; + } + function createVertex(p, u, n) { // Positions - var pi = (parseInt(p) - 1) * 3; + var pi = getOffset(p, positions, 3); var px = positions[pi + 0]; var py = positions[pi + 1]; var pz = positions[pi + 2]; + positionMin[0] = Math.min(px, positionMin[0]); positionMin[1] = Math.min(py, positionMin[1]); positionMin[2] = Math.min(pz, positionMin[2]); @@ -83,7 +94,7 @@ function processObj(objFile, info, materials, images, done) { // Normals if (hasNormals) { - var ni = (parseInt(n) - 1) * 3; + var ni = getOffset(n, normals, 3); var nx = normals[ni + 0]; var ny = normals[ni + 1]; var nz = normals[ni + 2]; @@ -93,7 +104,7 @@ function processObj(objFile, info, materials, images, done) { // UVs if (hasUVs) { if (defined(u)) { - var ui = (parseInt(u) - 1) * 2; + var ui = getOffset(u, uvs, 2); var ux = uvs[ui + 0]; var uy = uvs[ui + 1]; vertexArray.push(ux, uy); @@ -155,68 +166,67 @@ function processObj(objFile, info, materials, images, done) { var facePattern4 = /f( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))?/; var stream = fs.createReadStream(objFile, 'utf8'); + var reader = readline.createInterface({ + input : stream + }); - stream.on('data', function(chunk) { - var lines = chunk.split('\n'); - length = lines.length; - for (i = 0; i < length; ++i) { - var line = lines[i].trim(); - var result; - if ((line.length === 0) || (line.charAt(0) === '#')) { - continue; - } else if ((result = vertexPattern.exec(line)) !== null) { - positions.push( - parseFloat(result[1]), - parseFloat(result[2]), - parseFloat(result[3]) - ); - } else if ((result = normalPattern.exec(line) ) !== null) { - var nx = parseFloat(result[1]); - var ny = parseFloat(result[2]); - var nz = parseFloat(result[3]); - var normal = Cartesian3.normalize(new Cartesian3(nx, ny, nz), new Cartesian3()); - normals.push(normal.x, normal.y, normal.z); - } else if ((result = uvPattern.exec(line)) !== null) { - uvs.push( - parseFloat(result[1]), - parseFloat(result[2]) - ); - } else if ((result = facePattern1.exec(line)) !== null) { - addFace( - result[1], result[1], undefined, undefined, - result[2], result[2], undefined, undefined, - result[3], result[3], undefined, undefined, - result[4], result[4], undefined, undefined - ); - } else if ((result = facePattern2.exec(line)) !== null) { - addFace( - result[1], result[2], result[3], undefined, - result[4], result[5], result[6], undefined, - result[7], result[8], result[9], undefined, - result[10], result[11], result[12], undefined - ); - } else if ((result = facePattern3.exec(line)) !== null) { - addFace( - result[1], result[2], result[3], result[4], - result[5], result[6], result[7], result[8], - result[9], result[10], result[11], result[12], - result[13], result[14], result[15], result[16] - ); - } else if ((result = facePattern4.exec(line)) !== null) { - addFace( - result[1], result[2], undefined, result[3], - result[4], result[5], undefined, result[6], - result[7], result[8], undefined, result[9], - result[10], result[11], undefined, result[12] - ); - } else if (/^usemtl /.test(line)) { - var materialName = line.substring(7).trim(); - useMaterial(materialName); - } + reader.on('line', function(line) { + line = line.trim(); + var result; + if ((line.length === 0) || (line.charAt(0) === '#')) { + // Nothing to process + } else if ((result = vertexPattern.exec(line)) !== null) { + positions.push( + parseFloat(result[1]), + parseFloat(result[2]), + parseFloat(result[3]) + ); + } else if ((result = normalPattern.exec(line) ) !== null) { + var nx = parseFloat(result[1]); + var ny = parseFloat(result[2]); + var nz = parseFloat(result[3]); + var normal = Cartesian3.normalize(new Cartesian3(nx, ny, nz), new Cartesian3()); + normals.push(normal.x, normal.y, normal.z); + } else if ((result = uvPattern.exec(line)) !== null) { + uvs.push( + parseFloat(result[1]), + parseFloat(result[2]) + ); + } else if ((result = facePattern1.exec(line)) !== null) { + addFace( + result[1], result[1], undefined, undefined, + result[2], result[2], undefined, undefined, + result[3], result[3], undefined, undefined, + result[4], result[4], undefined, undefined + ); + } else if ((result = facePattern2.exec(line)) !== null) { + addFace( + result[1], result[2], result[3], undefined, + result[4], result[5], result[6], undefined, + result[7], result[8], result[9], undefined, + result[10], result[11], result[12], undefined + ); + } else if ((result = facePattern3.exec(line)) !== null) { + addFace( + result[1], result[2], result[3], result[4], + result[5], result[6], result[7], result[8], + result[9], result[10], result[11], result[12], + result[13], result[14], result[15], result[16] + ); + } else if ((result = facePattern4.exec(line)) !== null) { + addFace( + result[1], result[2], undefined, result[3], + result[4], result[5], undefined, result[6], + result[7], result[8], undefined, result[9], + result[10], result[11], undefined, result[12] + ); + } else if (/^usemtl /.test(line)) { + var materialName = line.substring(7).trim(); + useMaterial(materialName); } }); - stream.on('end', function() { + reader.on('close', function() { done({ vertexCount : vertexCount, vertexArray : vertexArray, @@ -299,9 +309,13 @@ function getObjInfo(objFile, inputPath, done) { var hasUVs = false; var stream = fs.createReadStream(objFile, 'utf8'); - stream.on('data', function(chunk) { + var reader = readline.createInterface({ + input : stream + }); + + reader.on('line', function(line) { if (!defined(mtlPath)) { - var mtllibMatches = chunk.match(/^mtllib.*/gm); + var mtllibMatches = line.match(/^mtllib.*/gm); if (mtllibMatches !== null) { var mtlFile = mtllibMatches[0].substring(7).trim(); mtlPath = mtlFile; @@ -311,20 +325,20 @@ function getObjInfo(objFile, inputPath, done) { } } if (!hasMaterialGroups) { - hasMaterialGroups = /^usemtl/gm.test(chunk); + hasMaterialGroups = /^usemtl/gm.test(line); } if (!hasPositions) { - hasPositions = /^v\s/gm.test(chunk); + hasPositions = /^v\s/gm.test(line); } if (!hasNormals) { - hasNormals = /^vn/gm.test(chunk); + hasNormals = /^vn/gm.test(line); } if (!hasUVs) { - hasUVs = /^vt/gm.test(chunk); + hasUVs = /^vt/gm.test(line); } }); - stream.on('end', function() { + reader.on('close', function() { if (!hasPositions) { throw new Error('Could not process OBJ file, no positions.'); }