mirror of
https://github.com/CesiumGS/obj2gltf.git
synced 2025-02-07 07:22:51 -05:00
refactored face line parsing to support multiline faces
This commit is contained in:
parent
7e82e90b35
commit
2396899f5d
151
lib/loadObj.js
151
lib/loadObj.js
@ -57,8 +57,15 @@ var facePattern2 = /f(\s+-?\d+\/-?\d+){3,}/;
|
||||
var facePattern3 = /f(\s+-?\d+\/-?\d+\/-?\d+){3,}/; // f vertex/uv/normal vertex/uv/normal vertex/uv/normal ...
|
||||
var facePattern4 = /f(\s+-?\d+\/\/-?\d+){3,}/; // f vertex//normal vertex//normal vertex//normal ...
|
||||
|
||||
var faceSpacePattern = /f?\s+/;
|
||||
var faceSpaceOrSlashPattern = /(f?\s+)|(\/+\s*)/g;
|
||||
// Just for line continuations
|
||||
var facePattern5 = /((\s|^)+-?\d+\/?(\s|$)){1,}/; // f vertex vertex vertex ...
|
||||
var facePattern6 = /((\s|^)+-?\d+\/-?\d+(\s|$)){1,}/; // f vertex/uv vertex/uv vertex/uv ...
|
||||
var facePattern7 = /((\s|^)+-?\d+\/-?\d+\/-?\d+(\s|$)+){1,}/; // f vertex/uv/normal vertex/uv/normal vertex/uv/normal ...
|
||||
var facePattern8 = /((\s|^)+-?\d+\/\/-?\d+(\s|$)){1,}/; // f vertex//normal vertex//normal vertex//normal ...
|
||||
|
||||
|
||||
var faceSpacePattern = /(f?\s+)|(\s+\/)|(\s*\\)/g;
|
||||
var faceSpaceOrSlashPattern = /(f?\s+)|(\/+\s*)|(\s+\/)|(\s*\\)/g;
|
||||
var scratchCartesian = new Cartesian3();
|
||||
|
||||
/**
|
||||
@ -101,6 +108,12 @@ function loadObj(objPath, options) {
|
||||
// All mtl paths seen in the obj
|
||||
var mtlPaths = [];
|
||||
|
||||
// Buffers for face data that spans multiple lines
|
||||
var faceVertices = [];
|
||||
var facePositions = [];
|
||||
var faceUvs = [];
|
||||
var faceNormals = [];
|
||||
|
||||
function getName(name) {
|
||||
return (name === '' ? undefined : name);
|
||||
}
|
||||
@ -166,6 +179,20 @@ function loadObj(objPath, options) {
|
||||
var zMag = Cartesian3.magnitude(zAxis);
|
||||
var min = Math.min(xMag, yMag, zMag);
|
||||
|
||||
// If all the points are on a line, just remove one of the zero dimensions
|
||||
if (xMag === 0 && (yMag === 0 || zMag === 0)) {
|
||||
var i;
|
||||
for (i = 0; i < positions.length; i++) {
|
||||
positions2D[i] = new Cartesian2(positions[i].y, positions[i].z);
|
||||
}
|
||||
return positions2D;
|
||||
} else if (yMag === 0 && zMag === 0) {
|
||||
for (i = 0; i < positions.length; i++) {
|
||||
positions2D[i] = new Cartesian2(positions[i].x, positions[i].y);
|
||||
}
|
||||
return positions2D;
|
||||
}
|
||||
|
||||
var center = obb.center;
|
||||
var planeXAxis;
|
||||
var planeYAxis;
|
||||
@ -200,7 +227,7 @@ function loadObj(objPath, options) {
|
||||
Plane.fromPointNormal(origin, normal, plane);
|
||||
ray.direction = normal;
|
||||
|
||||
for (var i = 0; i < positions.length; i++) {
|
||||
for (i = 0; i < positions.length; i++) {
|
||||
ray.origin = positions[i];
|
||||
|
||||
var intersectionPoint = IntersectionTests.rayPlane(ray, plane, intPoint);
|
||||
@ -279,6 +306,14 @@ function loadObj(objPath, options) {
|
||||
return index;
|
||||
}
|
||||
|
||||
function get3DPoint(index, result) {
|
||||
var pi = getOffset(index, positions, 3);
|
||||
var px = positions.get(pi + 0);
|
||||
var py = positions.get(pi + 1);
|
||||
var pz = positions.get(pi + 2);
|
||||
return Cartesian3.fromElements(px, py, pz, result);
|
||||
}
|
||||
|
||||
// Given a sequence of three points A B C, determine whether vector BC
|
||||
// "turns" clockwise (positive) or counter-clockwise (negative) from vector AB
|
||||
var scratch1 = new Cartesian3();
|
||||
@ -333,6 +368,7 @@ function loadObj(objPath, options) {
|
||||
|
||||
var i;
|
||||
for (i = 0; i < vertices.length; ++i) {
|
||||
|
||||
var u = (defined(uvs)) ? uvs[i] : undefined;
|
||||
var n = (defined(normals)) ? normals[i] : undefined;
|
||||
|
||||
@ -340,24 +376,18 @@ function loadObj(objPath, options) {
|
||||
vertexIndices.push(index);
|
||||
|
||||
// Collect the vertex positions as 3D points
|
||||
var pi = getOffset(index + 1, positions, 3);
|
||||
var px = mesh.positions.get(pi + 0);
|
||||
var py = mesh.positions.get(pi + 1);
|
||||
var pz = mesh.positions.get(pi + 2);
|
||||
positions3D.push(new Cartesian3(px, py, pz));
|
||||
positions3D.push(get3DPoint(positions[i], new Cartesian3()));
|
||||
}
|
||||
|
||||
var positions2D = projectTo2D(positions3D);
|
||||
|
||||
if (isConvex(positions2D)) {
|
||||
// Use the fan method to triangulate
|
||||
for (i=1; i < vertices.length-1; ++i) {
|
||||
primitive.indices.push(vertexIndices[0]);
|
||||
primitive.indices.push(vertexIndices[i]);
|
||||
primitive.indices.push(vertexIndices[i+1]);
|
||||
}
|
||||
} else {
|
||||
|
||||
// Since the projection doesn't respect winding order, reverse the order of
|
||||
// the vertices before triangulating to enforce counter clockwise.
|
||||
var windingOrder = PolygonPipeline.computeWindingOrder2D(positions2D);
|
||||
@ -372,7 +402,66 @@ function loadObj(objPath, options) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function trimEmpty(entry) { return entry.trim() !== ''; }
|
||||
|
||||
// Parse a line of face data.
|
||||
// Because face data can span multiple lines, attribute data is buffered in parallel lists
|
||||
// faceVertices : names of a vertices for caching
|
||||
// facePosition : indices into position array
|
||||
// faceUvs : indices into uv array
|
||||
// faceNormals : indices into normal array
|
||||
function parseFaceLine(line, hasUvs, hasNormals) {
|
||||
|
||||
// get vertex data (attributes '/' separated)
|
||||
faceVertices = faceVertices.concat(line.replace(faceSpacePattern, ' ').split(' ').filter(trimEmpty));
|
||||
// get all vertex attributes for this line
|
||||
var faceAttributes = line.replace(faceSpaceOrSlashPattern, ' ').split(' ').filter(trimEmpty);
|
||||
|
||||
var i;
|
||||
if (hasUvs && hasNormals) {
|
||||
for (i=0; i <= faceAttributes.length - 3; i += 3)
|
||||
{
|
||||
facePositions.push(faceAttributes[i]);
|
||||
faceUvs.push(faceAttributes[i+1]);
|
||||
faceNormals.push(faceAttributes[i+2]);
|
||||
}
|
||||
} else if (hasUvs) {
|
||||
for (i=0; i <= faceAttributes.length - 2; i += 2)
|
||||
{
|
||||
facePositions.push(faceAttributes[i]);
|
||||
faceUvs.push(faceAttributes[i+1]);
|
||||
}
|
||||
faceNormals = undefined;
|
||||
} else if (hasNormals) {
|
||||
for (i=0; i <= faceAttributes.length - 2; i += 2)
|
||||
{
|
||||
facePositions.push(faceAttributes[i]);
|
||||
faceNormals.push(faceAttributes[i+1]);
|
||||
}
|
||||
faceUvs = undefined;
|
||||
} else {
|
||||
for (i=0; i < faceAttributes.length; ++i)
|
||||
{
|
||||
facePositions.push(faceAttributes[i]);
|
||||
}
|
||||
faceUvs = undefined;
|
||||
faceNormals = undefined;
|
||||
}
|
||||
|
||||
// If there's a line continuation, buffer the results and don't create face yet
|
||||
if (line.slice(-1) === '\\') {
|
||||
return;
|
||||
}
|
||||
|
||||
addFace(faceVertices, facePositions, faceUvs, faceNormals);
|
||||
|
||||
// Clear buffered data once face has been added.
|
||||
faceVertices = [];
|
||||
facePositions = [];
|
||||
faceUvs = [];
|
||||
faceNormals = [];
|
||||
}
|
||||
|
||||
function parseLine(line) {
|
||||
@ -418,38 +507,18 @@ function loadObj(objPath, options) {
|
||||
} 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
|
||||
} else {
|
||||
var faceVertices = line.replace(faceSpacePattern, ' ').substring(1).split(' '); // get vertex data (attributes '/' separated)
|
||||
var faceAttributes = line.replace(faceSpaceOrSlashPattern, ' ').substring(1).split(' '); // get vertex attributes
|
||||
var facePositions = [];
|
||||
var faceUvs = [];
|
||||
var faceNormals = [];
|
||||
} else { // face line or invalid line
|
||||
// If we already have buffered data, this is a continued line
|
||||
var continuedLine = faceVertices.length > 0;
|
||||
|
||||
if (facePattern1.test(line)) { // format "f v v v ..."
|
||||
addFace(faceVertices, faceAttributes, undefined, undefined);
|
||||
} else if (facePattern2.test(line)) { // format "f v/uv v/uv v/uv ..."
|
||||
var i;
|
||||
for (i=0; i <= faceAttributes.length - 2; i += 2)
|
||||
{
|
||||
facePositions.push(faceAttributes[i]);
|
||||
faceUvs.push(faceAttributes[i+1]);
|
||||
}
|
||||
addFace(faceVertices, facePositions, faceUvs, undefined);
|
||||
} else if (facePattern3.test(line)) { // format "v/uv/n v/uv/n v/uv/n ..."
|
||||
for (i=0; i <= faceAttributes.length - 3; i += 3)
|
||||
{
|
||||
facePositions.push(faceAttributes[i]);
|
||||
faceUvs.push(faceAttributes[i+1]);
|
||||
faceNormals.push(faceAttributes[i+2]);
|
||||
}
|
||||
addFace(faceVertices, facePositions, faceUvs, faceNormals);
|
||||
} else if (facePattern4.test(line)) { // format "v//n v//n v//n ..."
|
||||
for (i=0; i <= faceAttributes.length - 2; i += 2)
|
||||
{
|
||||
facePositions.push(faceAttributes[i]);
|
||||
faceNormals.push(faceAttributes[i+1]);
|
||||
}
|
||||
addFace(faceVertices, facePositions, undefined, faceNormals);
|
||||
if (facePattern1.test(line) || (continuedLine && facePattern5.test(line))) { // format "f v v v ..."
|
||||
parseFaceLine(line, false, false);
|
||||
} else if (facePattern2.test(line) || (continuedLine && facePattern6.test(line))) { // format "f v/uv v/uv v/uv ..."
|
||||
parseFaceLine(line, true, false);
|
||||
} else if (facePattern3.test(line) || (continuedLine && facePattern7.test(line))) { // format "v/uv/n v/uv/n v/uv/n ..."
|
||||
parseFaceLine(line, true, true);
|
||||
} else if (facePattern4.test(line) || (continuedLine && facePattern8.test(line))) { // format "v//n v//n v//n ..."
|
||||
parseFaceLine(line, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user