mirror of https://github.com/CesiumGS/obj2gltf.git
Merge branch 'master' into gltf-2.0
This commit is contained in:
commit
72baced2ed
316
lib/loadObj.js
316
lib/loadObj.js
|
@ -8,10 +8,19 @@ var loadMtl = require('./loadMtl');
|
||||||
var outsideDirectory = require('./outsideDirectory');
|
var outsideDirectory = require('./outsideDirectory');
|
||||||
var readLines = require('./readLines');
|
var readLines = require('./readLines');
|
||||||
|
|
||||||
|
var Cartesian2 = Cesium.Cartesian2;
|
||||||
|
var Cartesian3 = Cesium.Cartesian3;
|
||||||
var ComponentDatatype = Cesium.ComponentDatatype;
|
var ComponentDatatype = Cesium.ComponentDatatype;
|
||||||
var defaultValue = Cesium.defaultValue;
|
var defaultValue = Cesium.defaultValue;
|
||||||
var defined = Cesium.defined;
|
var defined = Cesium.defined;
|
||||||
|
var IntersectionTests = Cesium.IntersectionTests;
|
||||||
|
var Matrix3 = Cesium.Matrix3;
|
||||||
|
var OrientedBoundingBox = Cesium.OrientedBoundingBox;
|
||||||
|
var Plane = Cesium.Plane;
|
||||||
|
var PolygonPipeline = Cesium.PolygonPipeline;
|
||||||
|
var Ray = Cesium.Ray;
|
||||||
var RuntimeError = Cesium.RuntimeError;
|
var RuntimeError = Cesium.RuntimeError;
|
||||||
|
var WindingOrder = Cesium.WindingOrder;
|
||||||
|
|
||||||
module.exports = loadObj;
|
module.exports = loadObj;
|
||||||
|
|
||||||
|
@ -38,13 +47,10 @@ function Primitive() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OBJ regex patterns are modified from ThreeJS (https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/OBJLoader.js)
|
// OBJ regex patterns are modified from ThreeJS (https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/OBJLoader.js)
|
||||||
var vertexPattern = /v( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // v float float float
|
var vertexPattern = /v( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // v float float float
|
||||||
var normalPattern = /vn( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vn float float float
|
var normalPattern = /vn( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vn float float float
|
||||||
var uvPattern = /vt( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vt float float
|
var uvPattern = /vt( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vt float float
|
||||||
var facePattern1 = /f( +-?\d+)\/?( +-?\d+)\/?( +-?\d+)\/?( +-?\d+)?\/?/; // f vertex vertex vertex ...
|
var facePattern = /(-?\d+)\/?(-?\d*)\/?(-?\d*)/g; // for any face format "f v", "f v/v", "f v//v", "f v/v/v"
|
||||||
var facePattern2 = /f( +(-?\d+)\/(-?\d+)\/?)( +(-?\d+)\/(-?\d+)\/?)( +(-?\d+)\/(-?\d+)\/?)( +(-?\d+)\/(-?\d+)\/?)?/; // f vertex/uv vertex/uv vertex/uv ...
|
|
||||||
var facePattern3 = /f( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))?/; // f vertex/uv/normal vertex/uv/normal vertex/uv/normal ...
|
|
||||||
var facePattern4 = /f( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))?/; // f vertex//normal vertex//normal vertex//normal ...
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse an obj file.
|
* Parse an obj file.
|
||||||
|
@ -78,6 +84,17 @@ function loadObj(objPath, options) {
|
||||||
// All mtl paths seen in the obj
|
// All mtl paths seen in the obj
|
||||||
var mtlPaths = [];
|
var mtlPaths = [];
|
||||||
|
|
||||||
|
// Buffers for face data that spans multiple lines
|
||||||
|
var lineBuffer = '';
|
||||||
|
|
||||||
|
// Used for parsing face data
|
||||||
|
var faceVertices = [];
|
||||||
|
var facePositions = [];
|
||||||
|
var faceUvs = [];
|
||||||
|
var faceNormals = [];
|
||||||
|
|
||||||
|
var vertexIndices = [];
|
||||||
|
|
||||||
function getName(name) {
|
function getName(name) {
|
||||||
return (name === '' ? undefined : name);
|
return (name === '' ? undefined : name);
|
||||||
}
|
}
|
||||||
|
@ -133,7 +150,7 @@ function loadObj(objPath, options) {
|
||||||
|
|
||||||
function createVertex(p, u, n) {
|
function createVertex(p, u, n) {
|
||||||
// Positions
|
// Positions
|
||||||
if (defined(p)) {
|
if (p.length > 0) {
|
||||||
var pi = getOffset(p, positions, 3);
|
var pi = getOffset(p, positions, 3);
|
||||||
var px = positions.get(pi + 0);
|
var px = positions.get(pi + 0);
|
||||||
var py = positions.get(pi + 1);
|
var py = positions.get(pi + 1);
|
||||||
|
@ -144,7 +161,7 @@ function loadObj(objPath, options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normals
|
// Normals
|
||||||
if (defined(n)) {
|
if (n.length > 0) {
|
||||||
var ni = getOffset(n, normals, 3);
|
var ni = getOffset(n, normals, 3);
|
||||||
var nx = normals.get(ni + 0);
|
var nx = normals.get(ni + 0);
|
||||||
var ny = normals.get(ni + 1);
|
var ny = normals.get(ni + 1);
|
||||||
|
@ -155,7 +172,7 @@ function loadObj(objPath, options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UVs
|
// UVs
|
||||||
if (defined(u)) {
|
if (u.length > 0) {
|
||||||
var ui = getOffset(u, uvs, 2);
|
var ui = getOffset(u, uvs, 2);
|
||||||
var ux = uvs.get(ui + 0);
|
var ux = uvs.get(ui + 0);
|
||||||
var uy = uvs.get(ui + 1);
|
var uy = uvs.get(ui + 1);
|
||||||
|
@ -182,21 +199,225 @@ function loadObj(objPath, options) {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addFace(v1, p1, u1, n1, v2, p2, u2, n2, v3, p3, u3, n3, v4, p4, u4, n4) {
|
// Given a set of 3D points, project them onto whichever axis will produce the least distortion.
|
||||||
var index1 = addVertex(v1, p1, u1, n1);
|
var scratchIntersectionPoint = new Cartesian3();
|
||||||
var index2 = addVertex(v2, p2, u2, n2);
|
var scratchXAxis = new Cartesian3();
|
||||||
var index3 = addVertex(v3, p3, u3, n3);
|
var scratchYAxis = new Cartesian3();
|
||||||
|
var scratchZAxis = new Cartesian3();
|
||||||
|
var scratchOrigin = new Cartesian3();
|
||||||
|
var scratchNormal = new Cartesian3();
|
||||||
|
var scratchRay = new Ray();
|
||||||
|
var scratchPlane = new Plane(Cesium.Cartesian3.UNIT_X, 0);
|
||||||
|
var scratchPositions2D = [new Cartesian2(), new Cartesian2(), new Cartesian2()];
|
||||||
|
function projectTo2D(positions) {
|
||||||
|
var positions2D = [];
|
||||||
|
var obb = OrientedBoundingBox.fromPoints(positions);
|
||||||
|
var halfAxes = obb.halfAxes;
|
||||||
|
Matrix3.getColumn(halfAxes, 0, scratchXAxis);
|
||||||
|
Matrix3.getColumn(halfAxes, 1, scratchYAxis);
|
||||||
|
Matrix3.getColumn(halfAxes, 2, scratchZAxis);
|
||||||
|
|
||||||
primitive.indices.push(index1);
|
var xMag = Cartesian3.magnitude(scratchXAxis);
|
||||||
primitive.indices.push(index2);
|
var yMag = Cartesian3.magnitude(scratchYAxis);
|
||||||
primitive.indices.push(index3);
|
var zMag = Cartesian3.magnitude(scratchZAxis);
|
||||||
|
var min = Math.min(xMag, yMag, zMag);
|
||||||
|
|
||||||
// Triangulate if the face is a quad
|
var i;
|
||||||
if (defined(v4)) {
|
// If all the points are on a line, just remove one of the zero dimensions
|
||||||
var index4 = addVertex(v4, p4, u4, n4);
|
if (xMag === 0 && (yMag === 0 || zMag === 0)) {
|
||||||
|
for (i = 0; i < positions.length; i++) {
|
||||||
|
if (i === scratchPositions2D.length) {
|
||||||
|
scratchPositions2D.push(new Cartesian2());
|
||||||
|
}
|
||||||
|
positions2D[i] = new Cartesian2.fromElements(positions[i].y, positions[i].z, scratchPositions2D[i]);
|
||||||
|
}
|
||||||
|
return positions2D;
|
||||||
|
} else if (yMag === 0 && zMag === 0) {
|
||||||
|
for (i = 0; i < positions.length; i++) {
|
||||||
|
if (i === scratchPositions2D.length) {
|
||||||
|
scratchPositions2D.push(new Cartesian2());
|
||||||
|
}
|
||||||
|
positions2D[i] = new Cartesian2.fromElements(positions[i].x, positions[i].y, scratchPositions2D[i]);
|
||||||
|
}
|
||||||
|
return positions2D;
|
||||||
|
}
|
||||||
|
|
||||||
|
var center = obb.center;
|
||||||
|
var planeXAxis;
|
||||||
|
var planeYAxis;
|
||||||
|
if (min === xMag) {
|
||||||
|
if (!scratchXAxis.equals(Cartesian3.ZERO)) {
|
||||||
|
Cartesian3.add(center, scratchXAxis, scratchOrigin);
|
||||||
|
Cartesian3.normalize(scratchXAxis, scratchNormal);
|
||||||
|
}
|
||||||
|
planeXAxis = Cartesian3.normalize(scratchYAxis, scratchYAxis);
|
||||||
|
planeYAxis = Cartesian3.normalize(scratchZAxis, scratchZAxis);
|
||||||
|
} else if (min === yMag) {
|
||||||
|
if (!scratchYAxis.equals(Cartesian3.ZERO)) {
|
||||||
|
Cartesian3.add(center, scratchYAxis, scratchOrigin);
|
||||||
|
Cartesian3.normalize(scratchYAxis, scratchNormal);
|
||||||
|
}
|
||||||
|
planeXAxis = Cartesian3.normalize(scratchXAxis, scratchXAxis);
|
||||||
|
planeYAxis = Cartesian3.normalize(scratchZAxis, scratchZAxis);
|
||||||
|
} else {
|
||||||
|
if (!scratchZAxis.equals(Cartesian3.ZERO)) {
|
||||||
|
Cartesian3.add(center, scratchZAxis, scratchOrigin);
|
||||||
|
Cartesian3.normalize(scratchZAxis, scratchNormal);
|
||||||
|
}
|
||||||
|
planeXAxis = Cartesian3.normalize(scratchXAxis, scratchXAxis);
|
||||||
|
planeYAxis = Cartesian3.normalize(scratchYAxis, scratchYAxis);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (min === 0) {
|
||||||
|
scratchNormal = Cartesian3.cross(planeXAxis, planeYAxis, scratchNormal);
|
||||||
|
scratchNormal = Cartesian3.normalize(scratchNormal, scratchNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
Plane.fromPointNormal(scratchOrigin, scratchNormal, scratchPlane);
|
||||||
|
scratchRay.direction = scratchNormal;
|
||||||
|
|
||||||
|
for (i = 0; i < positions.length; i++) {
|
||||||
|
scratchRay.origin = positions[i];
|
||||||
|
|
||||||
|
var intersectionPoint = IntersectionTests.rayPlane(scratchRay, scratchPlane, scratchIntersectionPoint);
|
||||||
|
|
||||||
|
if (!defined(intersectionPoint)) {
|
||||||
|
Cartesian3.negate(scratchRay.direction, scratchRay.direction);
|
||||||
|
intersectionPoint = IntersectionTests.rayPlane(scratchRay, scratchPlane, scratchIntersectionPoint);
|
||||||
|
}
|
||||||
|
var v = Cartesian3.subtract(intersectionPoint, scratchOrigin, intersectionPoint);
|
||||||
|
var x = Cartesian3.dot(planeXAxis, v);
|
||||||
|
var y = Cartesian3.dot(planeYAxis, v);
|
||||||
|
|
||||||
|
if (i === scratchPositions2D.length) {
|
||||||
|
scratchPositions2D.push(new Cartesian2());
|
||||||
|
}
|
||||||
|
|
||||||
|
positions2D[i] = new Cartesian2.fromElements(x, y, scratchPositions2D[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return positions2D;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get3DNormal(index, result) {
|
||||||
|
var ni = getOffset(index, normals, 3);
|
||||||
|
var nx = normals.get(ni + 0);
|
||||||
|
var ny = normals.get(ni + 1);
|
||||||
|
var nz = normals.get(ni + 2);
|
||||||
|
return Cartesian3.fromElements(nx, ny, nz, 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();
|
||||||
|
var scratch2 = new Cartesian3();
|
||||||
|
function getTurnDirection(pointA, pointB, pointC) {
|
||||||
|
var vector1 = Cartesian2.subtract(pointA, pointB, scratch1);
|
||||||
|
var vector2 = Cartesian2.subtract(pointC, pointB, scratch2);
|
||||||
|
return vector1.x * vector2.y - vector1.y * vector2.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given the cartesian 2 vertices of a polygon, determine if convex
|
||||||
|
function isConvex(positions2D) {
|
||||||
|
var turnDirection = getTurnDirection(positions2D[0], positions2D[1], positions2D[2]);
|
||||||
|
for (var i=1; i < positions2D.length-2; ++i) {
|
||||||
|
var currentTurnDirection = getTurnDirection(positions2D[i], positions2D[i+1], positions2D[i+2]);
|
||||||
|
if (turnDirection * currentTurnDirection < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var scratch3 = new Cartesian3();
|
||||||
|
var scratch4 = new Cartesian3();
|
||||||
|
var scratch5 = new Cartesian3();
|
||||||
|
// Checks if winding order matches the given normal.
|
||||||
|
function checkWindingCorrect(positionIndex1, positionIndex2, positionIndex3, normal) {
|
||||||
|
var A = get3DPoint(positionIndex1, scratch1);
|
||||||
|
var B = get3DPoint(positionIndex2, scratch2);
|
||||||
|
var C = get3DPoint(positionIndex3, scratch3);
|
||||||
|
|
||||||
|
var BA = Cartesian3.subtract(B, A, scratch4);
|
||||||
|
var CA = Cartesian3.subtract(C, A, scratch5);
|
||||||
|
var cross = Cartesian3.cross(BA, CA, scratch3);
|
||||||
|
|
||||||
|
return (Cartesian3.dot(normal, cross) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addTriangle(index1, index2, index3, correctWinding) {
|
||||||
|
if (correctWinding) {
|
||||||
|
primitive.indices.push(index1);
|
||||||
|
primitive.indices.push(index2);
|
||||||
|
primitive.indices.push(index3);
|
||||||
|
} else {
|
||||||
primitive.indices.push(index1);
|
primitive.indices.push(index1);
|
||||||
primitive.indices.push(index3);
|
primitive.indices.push(index3);
|
||||||
primitive.indices.push(index4);
|
primitive.indices.push(index2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var scratchPositions3D = [new Cartesian3(), new Cartesian3(), new Cartesian3()];
|
||||||
|
function addFace(vertices, positions, uvs, normals) {
|
||||||
|
var isWindingCorrect = true;
|
||||||
|
var faceNormal;
|
||||||
|
|
||||||
|
// If normals are defined, find a face normal to use in winding order sanitization.
|
||||||
|
// If no face normal, we have to assume the winding is correct.
|
||||||
|
if (normals[0].length > 0) {
|
||||||
|
faceNormal = get3DNormal(normals[0], scratchNormal);
|
||||||
|
isWindingCorrect = checkWindingCorrect(positions[0], positions[1], positions[2], faceNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vertices.length === 3) {
|
||||||
|
var index1 = addVertex(vertices[0], positions[0], uvs[0], normals[0]);
|
||||||
|
var index2 = addVertex(vertices[1], positions[1], uvs[1], normals[1]);
|
||||||
|
var index3 = addVertex(vertices[2], positions[2], uvs[2], normals[2]);
|
||||||
|
addTriangle(index1, index2, index3, isWindingCorrect);
|
||||||
|
} else { // Triangulate if the face is not a triangle
|
||||||
|
var positions3D = [];
|
||||||
|
vertexIndices.length = 0;
|
||||||
|
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < vertices.length; ++i) {
|
||||||
|
var index = addVertex(vertices[i], positions[i], uvs[i], normals[i]);
|
||||||
|
vertexIndices.push(index);
|
||||||
|
|
||||||
|
// Collect the vertex positions as 3D points
|
||||||
|
if (i === scratchPositions3D.length) {
|
||||||
|
scratchPositions3D.push(new Cartesian3());
|
||||||
|
}
|
||||||
|
positions3D.push(get3DPoint(positions[i], scratchPositions3D[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
var positions2D = projectTo2D(positions3D);
|
||||||
|
|
||||||
|
if (isConvex(positions2D)) {
|
||||||
|
for (i=1; i < vertices.length-1; ++i) {
|
||||||
|
addTriangle(vertexIndices[0], vertexIndices[i], vertexIndices[i+1], isWindingCorrect);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Since the projection doesn't preserve winding order, reverse the order of
|
||||||
|
// the vertices before triangulating to enforce counter clockwise.
|
||||||
|
var projectedWindingOrder = PolygonPipeline.computeWindingOrder2D(positions2D);
|
||||||
|
if (projectedWindingOrder === WindingOrder.CLOCKWISE) {
|
||||||
|
positions2D.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use an ear-clipping algorithm to triangulate
|
||||||
|
var positionIndices = PolygonPipeline.triangulate(positions2D);
|
||||||
|
for (i = 0; i < positionIndices.length-2; i += 3) {
|
||||||
|
addTriangle(vertexIndices[positionIndices[i]], vertexIndices[positionIndices[i+1]], vertexIndices[positionIndices[i+2]], isWindingCorrect);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,35 +449,30 @@ function loadObj(objPath, options) {
|
||||||
normals.push(parseFloat(result[3]));
|
normals.push(parseFloat(result[3]));
|
||||||
} else if ((result = uvPattern.exec(line)) !== null) {
|
} else if ((result = uvPattern.exec(line)) !== null) {
|
||||||
uvs.push(parseFloat(result[1]));
|
uvs.push(parseFloat(result[1]));
|
||||||
uvs.push(1.0 - parseFloat(result[2])); // Flip y so 0.0 is the bottom of the texture
|
uvs.push(1.0 - parseFloat(result[2])); // Flip y so 0.0 is the bottom of the image
|
||||||
} else if ((result = facePattern1.exec(line)) !== null) {
|
} else { // face line or invalid line
|
||||||
addFace(
|
// Because face lines can contain n vertices, we use a line buffer in case the face data spans multiple lines.
|
||||||
result[1], result[1], undefined, undefined,
|
// If there's a line continuation don't create face yet
|
||||||
result[2], result[2], undefined, undefined,
|
if (line.slice(-1) === '\\') {
|
||||||
result[3], result[3], undefined, undefined,
|
lineBuffer += line.substring(0, line.length-1);
|
||||||
result[4], result[4], undefined, undefined
|
return;
|
||||||
);
|
}
|
||||||
} else if ((result = facePattern2.exec(line)) !== null) {
|
lineBuffer += line;
|
||||||
addFace(
|
if (lineBuffer.substring(0, 2) === 'f ') {
|
||||||
result[1], result[2], result[3], undefined,
|
while ((result = facePattern.exec(lineBuffer)) !== null) {
|
||||||
result[4], result[5], result[6], undefined,
|
faceVertices.push(result[0]);
|
||||||
result[7], result[8], result[9], undefined,
|
facePositions.push(result[1]);
|
||||||
result[10], result[11], result[12], undefined
|
faceUvs.push(result[2]);
|
||||||
);
|
faceNormals.push(result[3]);
|
||||||
} else if ((result = facePattern3.exec(line)) !== null) {
|
}
|
||||||
addFace(
|
addFace(faceVertices, facePositions, faceUvs, faceNormals);
|
||||||
result[1], result[2], result[3], result[4],
|
|
||||||
result[5], result[6], result[7], result[8],
|
faceVertices.length = 0;
|
||||||
result[9], result[10], result[11], result[12],
|
facePositions.length = 0;
|
||||||
result[13], result[14], result[15], result[16]
|
faceNormals.length = 0;
|
||||||
);
|
faceUvs.length = 0;
|
||||||
} else if ((result = facePattern4.exec(line)) !== null) {
|
}
|
||||||
addFace(
|
lineBuffer = '';
|
||||||
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]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
# Blender MTL File: 'box.blend'
|
# Blender MTL File: 'None'
|
||||||
# Material Count: 1
|
# Material Count: 1
|
||||||
|
|
||||||
newmtl Material
|
newmtl None
|
||||||
Ns 96.078431
|
Ns 0
|
||||||
Ka 0.000000 0.000000 0.000000
|
Ka 0.000000 0.000000 0.000000
|
||||||
Kd 0.640000 0.640000 0.640000
|
Kd 0.8 0.8 0.8
|
||||||
Ks 0.500000 0.500000 0.500000
|
Ks 0.8 0.8 0.8
|
||||||
Ke 0.000000 0.000000 0.000000
|
d 1
|
||||||
Ni 1.000000
|
|
||||||
d 1.000000
|
|
||||||
illum 2
|
illum 2
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Blender v2.78 (sub 0) OBJ File: 'box.blend'
|
# Blender v2.78 (sub 0) OBJ File: ''
|
||||||
# www.blender.org
|
# www.blender.org
|
||||||
mtllib box-triangles.mtl
|
mtllib box-triangles.mtl
|
||||||
o Cube
|
o Cube_Cube.001
|
||||||
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
|
||||||
|
@ -10,37 +10,23 @@ 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 -1.0000 0.0000 0.0000
|
vn -1.0000 0.0000 0.0000
|
||||||
vn 0.0000 0.0000 -1.0000
|
vn 0.0000 0.0000 -1.0000
|
||||||
vn 1.0000 0.0000 0.0000
|
vn 1.0000 0.0000 0.0000
|
||||||
vn 0.0000 0.0000 1.0000
|
vn 0.0000 0.0000 1.0000
|
||||||
vn 0.0000 -1.0000 0.0000
|
vn 0.0000 -1.0000 0.0000
|
||||||
vn 0.0000 1.0000 0.0000
|
vn 0.0000 1.0000 0.0000
|
||||||
usemtl Material
|
usemtl None
|
||||||
s off
|
s off
|
||||||
f 1/1/1 2/2/1 4/3/1 3/4/1
|
f 2//1 3//1 1//1
|
||||||
f 3/5/2 4/6/2 8/7/2 7/8/2
|
f 4//2 7//2 3//2
|
||||||
f 7/9/3 8/10/3 6/11/3 5/12/3
|
f 8//3 5//3 7//3
|
||||||
f 5/13/4 6/14/4 2/15/4 1/16/4
|
f 6//4 1//4 5//4
|
||||||
f 3/5/5 7/17/5 5/18/5 1/16/5
|
f 7//5 1//5 3//5
|
||||||
f 8/19/6 4/6/6 2/15/6 6/20/6
|
f 4//6 6//6 8//6
|
||||||
|
f 2//1 4//1 3//1
|
||||||
|
f 4//2 8//2 7//2
|
||||||
|
f 8//3 6//3 5//3
|
||||||
|
f 6//4 2//4 1//4
|
||||||
|
f 7//5 5//5 1//5
|
||||||
|
f 4//6 2//6 6//6
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Blender MTL File: 'None'
|
||||||
|
# Material Count: 1
|
||||||
|
|
||||||
|
newmtl None
|
||||||
|
Ns 0
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 0.8 0.8 0.8
|
||||||
|
Ks 0.8 0.8 0.8
|
||||||
|
d 1
|
||||||
|
illum 2
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Blender v2.78 (sub 0) OBJ File: ''
|
||||||
|
# www.blender.org
|
||||||
|
mtllib concave.mtl
|
||||||
|
o Plane
|
||||||
|
v -1.458150 0.363522 1.000000
|
||||||
|
v 0.541850 0.363522 1.000000
|
||||||
|
v -1.458150 0.363522 -1.000000
|
||||||
|
v 0.541850 0.363522 -1.000000
|
||||||
|
v -0.336510 0.363522 0.000000
|
||||||
|
v -1.458150 -0.363522 1.000000
|
||||||
|
v 0.541850 -0.363522 1.000000
|
||||||
|
v -1.458150 -0.363522 -1.000000
|
||||||
|
v 0.541850 -0.363522 -1.000000
|
||||||
|
v -0.336510 -0.363522 0.000000
|
||||||
|
vn 0.0000 1.0000 0.0000
|
||||||
|
vn 0.0000 -1.0000 0.0000
|
||||||
|
vn 0.7513 0.0000 -0.6599
|
||||||
|
vn 0.7513 0.0000 0.6599
|
||||||
|
vn -1.0000 0.0000 0.0000
|
||||||
|
vn 0.0000 0.0000 -1.0000
|
||||||
|
vn 0.0000 0.0000 1.0000
|
||||||
|
usemtl None
|
||||||
|
s off
|
||||||
|
f 1//1 2//1 5//1 4//1 3//1
|
||||||
|
f 6//2 8//2 9//2 10//2 7//2
|
||||||
|
f 2//3 7//3 10//3 5//3
|
||||||
|
f 5//4 10//4 9//4 4//4
|
||||||
|
f 3//5 8//5 6//5 1//5
|
||||||
|
f 4//6 9//6 8//6 3//6
|
||||||
|
f 1//7 6//7 7//7 2//7
|
|
@ -27,6 +27,7 @@ var objTexturedPath = 'specs/data/box-textured/box-textured.obj';
|
||||||
var objMissingTexturePath = 'specs/data/box-missing-texture/box-missing-texture.obj';
|
var objMissingTexturePath = 'specs/data/box-missing-texture/box-missing-texture.obj';
|
||||||
var objSubdirectoriesPath = 'specs/data/box-subdirectories/box-textured.obj';
|
var objSubdirectoriesPath = 'specs/data/box-subdirectories/box-textured.obj';
|
||||||
var objInvalidContentsPath = 'specs/data/box/box.mtl';
|
var objInvalidContentsPath = 'specs/data/box/box.mtl';
|
||||||
|
var objConcavePath = 'specs/data/concave/concave.obj';
|
||||||
var objInvalidPath = 'invalid.obj';
|
var objInvalidPath = 'invalid.obj';
|
||||||
|
|
||||||
function getMeshes(data) {
|
function getMeshes(data) {
|
||||||
|
@ -190,6 +191,16 @@ describe('loadObj', function() {
|
||||||
}), done).toResolve();
|
}), done).toResolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('loads obj with concave face containing 5 vertices', function(done) {
|
||||||
|
expect(loadObj(objConcavePath, options)
|
||||||
|
.then(function(data) {
|
||||||
|
var mesh = getMeshes(data)[0];
|
||||||
|
var primitive = getPrimitives(data)[0];
|
||||||
|
expect(mesh.positions.length / 3).toBe(30);
|
||||||
|
expect(primitive.indices.length).toBe(48);
|
||||||
|
}), done).toResolve();
|
||||||
|
});
|
||||||
|
|
||||||
it('loads obj with usemtl only', function(done) {
|
it('loads obj with usemtl only', function(done) {
|
||||||
expect(loadObj(objUsemtlPath, options)
|
expect(loadObj(objUsemtlPath, options)
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
|
|
Loading…
Reference in New Issue