Read lines from stream and handle negative indices

This commit is contained in:
Sean Lilley 2016-06-22 16:16:29 -04:00
parent fec860ede0
commit 31760c34a8
2 changed files with 84 additions and 70 deletions

View File

@ -327,7 +327,7 @@ function createGltf(data, inputPath, modelName, done) {
} }
if (bufferSeparate) { if (bufferSeparate) {
var bufferPath = path.join(path.dirname(inputPath), modelName + '.bin'); var bufferPath = path.join(inputPath, modelName + '.bin');
fs.writeFile(bufferPath, buffer, function(err) { fs.writeFile(bufferPath, buffer, function(err) {
if (err) { if (err) {
throw err; throw err;

View File

@ -2,6 +2,7 @@
var async = require('async'); var async = require('async');
var fs = require('fs-extra'); var fs = require('fs-extra');
var path = require('path'); var path = require('path');
var readline = require('readline');
var loadImage = require('./image'); var loadImage = require('./image');
var Material = require('./mtl'); var Material = require('./mtl');
var Cesium = require('cesium'); var Cesium = require('cesium');
@ -33,7 +34,7 @@ function processObj(objFile, info, materials, images, done) {
var uvs = []; var uvs = [];
var positionMin = [Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE]; 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 hasNormals = info.hasNormals;
var hasUVs = info.hasUVs; var hasUVs = info.hasUVs;
@ -67,12 +68,22 @@ function processObj(objFile, info, materials, images, done) {
useDefaultMaterial(); 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) { function createVertex(p, u, n) {
// Positions // Positions
var pi = (parseInt(p) - 1) * 3; var pi = getOffset(p, positions, 3);
var px = positions[pi + 0]; var px = positions[pi + 0];
var py = positions[pi + 1]; var py = positions[pi + 1];
var pz = positions[pi + 2]; var pz = positions[pi + 2];
positionMin[0] = Math.min(px, positionMin[0]); positionMin[0] = Math.min(px, positionMin[0]);
positionMin[1] = Math.min(py, positionMin[1]); positionMin[1] = Math.min(py, positionMin[1]);
positionMin[2] = Math.min(pz, positionMin[2]); positionMin[2] = Math.min(pz, positionMin[2]);
@ -83,7 +94,7 @@ function processObj(objFile, info, materials, images, done) {
// Normals // Normals
if (hasNormals) { if (hasNormals) {
var ni = (parseInt(n) - 1) * 3; var ni = getOffset(n, normals, 3);
var nx = normals[ni + 0]; var nx = normals[ni + 0];
var ny = normals[ni + 1]; var ny = normals[ni + 1];
var nz = normals[ni + 2]; var nz = normals[ni + 2];
@ -93,7 +104,7 @@ function processObj(objFile, info, materials, images, done) {
// UVs // UVs
if (hasUVs) { if (hasUVs) {
if (defined(u)) { if (defined(u)) {
var ui = (parseInt(u) - 1) * 2; var ui = getOffset(u, uvs, 2);
var ux = uvs[ui + 0]; var ux = uvs[ui + 0];
var uy = uvs[ui + 1]; var uy = uvs[ui + 1];
vertexArray.push(ux, uy); 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 facePattern4 = /f( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))?/;
var stream = fs.createReadStream(objFile, 'utf8'); var stream = fs.createReadStream(objFile, 'utf8');
var reader = readline.createInterface({
input : stream
});
stream.on('data', function(chunk) { reader.on('line', function(line) {
var lines = chunk.split('\n'); line = line.trim();
length = lines.length; var result;
for (i = 0; i < length; ++i) { if ((line.length === 0) || (line.charAt(0) === '#')) {
var line = lines[i].trim(); // Nothing to process
var result; } else if ((result = vertexPattern.exec(line)) !== null) {
if ((line.length === 0) || (line.charAt(0) === '#')) { positions.push(
continue; parseFloat(result[1]),
} else if ((result = vertexPattern.exec(line)) !== null) { parseFloat(result[2]),
positions.push( parseFloat(result[3])
parseFloat(result[1]), );
parseFloat(result[2]), } else if ((result = normalPattern.exec(line) ) !== null) {
parseFloat(result[3]) var nx = parseFloat(result[1]);
); var ny = parseFloat(result[2]);
} else if ((result = normalPattern.exec(line) ) !== null) { var nz = parseFloat(result[3]);
var nx = parseFloat(result[1]); var normal = Cartesian3.normalize(new Cartesian3(nx, ny, nz), new Cartesian3());
var ny = parseFloat(result[2]); normals.push(normal.x, normal.y, normal.z);
var nz = parseFloat(result[3]); } else if ((result = uvPattern.exec(line)) !== null) {
var normal = Cartesian3.normalize(new Cartesian3(nx, ny, nz), new Cartesian3()); uvs.push(
normals.push(normal.x, normal.y, normal.z); parseFloat(result[1]),
} else if ((result = uvPattern.exec(line)) !== null) { parseFloat(result[2])
uvs.push( );
parseFloat(result[1]), } else if ((result = facePattern1.exec(line)) !== null) {
parseFloat(result[2]) addFace(
); result[1], result[1], undefined, undefined,
} else if ((result = facePattern1.exec(line)) !== null) { result[2], result[2], undefined, undefined,
addFace( result[3], result[3], undefined, undefined,
result[1], result[1], undefined, undefined, result[4], result[4], undefined, undefined
result[2], result[2], undefined, undefined, );
result[3], result[3], undefined, undefined, } else if ((result = facePattern2.exec(line)) !== null) {
result[4], result[4], undefined, undefined addFace(
); result[1], result[2], result[3], undefined,
} else if ((result = facePattern2.exec(line)) !== null) { result[4], result[5], result[6], undefined,
addFace( result[7], result[8], result[9], undefined,
result[1], result[2], result[3], undefined, result[10], result[11], result[12], undefined
result[4], result[5], result[6], undefined, );
result[7], result[8], result[9], undefined, } else if ((result = facePattern3.exec(line)) !== null) {
result[10], result[11], result[12], undefined addFace(
); result[1], result[2], result[3], result[4],
} else if ((result = facePattern3.exec(line)) !== null) { result[5], result[6], result[7], result[8],
addFace( result[9], result[10], result[11], result[12],
result[1], result[2], result[3], result[4], result[13], result[14], result[15], result[16]
result[5], result[6], result[7], result[8], );
result[9], result[10], result[11], result[12], } else if ((result = facePattern4.exec(line)) !== null) {
result[13], result[14], result[15], result[16] addFace(
); result[1], result[2], undefined, result[3],
} else if ((result = facePattern4.exec(line)) !== null) { result[4], result[5], undefined, result[6],
addFace( result[7], result[8], undefined, result[9],
result[1], result[2], undefined, result[3], result[10], result[11], undefined, result[12]
result[4], result[5], undefined, result[6], );
result[7], result[8], undefined, result[9], } else if (/^usemtl /.test(line)) {
result[10], result[11], undefined, result[12] var materialName = line.substring(7).trim();
); useMaterial(materialName);
} else if (/^usemtl /.test(line)) {
var materialName = line.substring(7).trim();
useMaterial(materialName);
}
} }
}); });
stream.on('end', function() { reader.on('close', function() {
done({ done({
vertexCount : vertexCount, vertexCount : vertexCount,
vertexArray : vertexArray, vertexArray : vertexArray,
@ -299,9 +309,13 @@ function getObjInfo(objFile, inputPath, done) {
var hasUVs = false; var hasUVs = false;
var stream = fs.createReadStream(objFile, 'utf8'); 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)) { if (!defined(mtlPath)) {
var mtllibMatches = chunk.match(/^mtllib.*/gm); var mtllibMatches = line.match(/^mtllib.*/gm);
if (mtllibMatches !== null) { if (mtllibMatches !== null) {
var mtlFile = mtllibMatches[0].substring(7).trim(); var mtlFile = mtllibMatches[0].substring(7).trim();
mtlPath = mtlFile; mtlPath = mtlFile;
@ -311,20 +325,20 @@ function getObjInfo(objFile, inputPath, done) {
} }
} }
if (!hasMaterialGroups) { if (!hasMaterialGroups) {
hasMaterialGroups = /^usemtl/gm.test(chunk); hasMaterialGroups = /^usemtl/gm.test(line);
} }
if (!hasPositions) { if (!hasPositions) {
hasPositions = /^v\s/gm.test(chunk); hasPositions = /^v\s/gm.test(line);
} }
if (!hasNormals) { if (!hasNormals) {
hasNormals = /^vn/gm.test(chunk); hasNormals = /^vn/gm.test(line);
} }
if (!hasUVs) { if (!hasUVs) {
hasUVs = /^vt/gm.test(chunk); hasUVs = /^vt/gm.test(line);
} }
}); });
stream.on('end', function() { reader.on('close', function() {
if (!hasPositions) { if (!hasPositions) {
throw new Error('Could not process OBJ file, no positions.'); throw new Error('Could not process OBJ file, no positions.');
} }