mirror of
https://github.com/CesiumGS/obj2gltf.git
synced 2024-11-30 03:50:14 -05:00
Fix tabs
This commit is contained in:
parent
601fca2794
commit
0f0bb8296a
@ -1,6 +1,10 @@
|
|||||||
Change Log
|
Change Log
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
### 3.0.3 2019-??-??
|
||||||
|
|
||||||
|
* Fixed parsing obj files that contain tabs.
|
||||||
|
|
||||||
### 3.0.2 2019-03-21
|
### 3.0.2 2019-03-21
|
||||||
|
|
||||||
* Fixed a crash when saving separate resources that would exceed the Node buffer size limit. [#173](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/173)
|
* Fixed a crash when saving separate resources that would exceed the Node buffer size limit. [#173](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/173)
|
||||||
|
@ -96,7 +96,7 @@ function loadMtl(mtlPath, options) {
|
|||||||
if (/^newmtl/i.test(line)) {
|
if (/^newmtl/i.test(line)) {
|
||||||
const name = line.substring(7).trim();
|
const name = line.substring(7).trim();
|
||||||
createMaterial(name);
|
createMaterial(name);
|
||||||
} else if (/^Ka /i.test(line)) {
|
} else if (/^Ka\s+/i.test(line)) {
|
||||||
values = line.substring(3).trim().split(' ');
|
values = line.substring(3).trim().split(' ');
|
||||||
material.ambientColor = [
|
material.ambientColor = [
|
||||||
parseFloat(values[0]),
|
parseFloat(values[0]),
|
||||||
@ -104,7 +104,7 @@ function loadMtl(mtlPath, options) {
|
|||||||
parseFloat(values[2]),
|
parseFloat(values[2]),
|
||||||
1.0
|
1.0
|
||||||
];
|
];
|
||||||
} else if (/^Ke /i.test(line)) {
|
} else if (/^Ke\s+/i.test(line)) {
|
||||||
values = line.substring(3).trim().split(' ');
|
values = line.substring(3).trim().split(' ');
|
||||||
material.emissiveColor = [
|
material.emissiveColor = [
|
||||||
parseFloat(values[0]),
|
parseFloat(values[0]),
|
||||||
@ -112,7 +112,7 @@ function loadMtl(mtlPath, options) {
|
|||||||
parseFloat(values[2]),
|
parseFloat(values[2]),
|
||||||
1.0
|
1.0
|
||||||
];
|
];
|
||||||
} else if (/^Kd /i.test(line)) {
|
} else if (/^Kd\s+/i.test(line)) {
|
||||||
values = line.substring(3).trim().split(' ');
|
values = line.substring(3).trim().split(' ');
|
||||||
material.diffuseColor = [
|
material.diffuseColor = [
|
||||||
parseFloat(values[0]),
|
parseFloat(values[0]),
|
||||||
@ -120,7 +120,7 @@ function loadMtl(mtlPath, options) {
|
|||||||
parseFloat(values[2]),
|
parseFloat(values[2]),
|
||||||
1.0
|
1.0
|
||||||
];
|
];
|
||||||
} else if (/^Ks /i.test(line)) {
|
} else if (/^Ks\s+/i.test(line)) {
|
||||||
values = line.substring(3).trim().split(' ');
|
values = line.substring(3).trim().split(' ');
|
||||||
material.specularColor = [
|
material.specularColor = [
|
||||||
parseFloat(values[0]),
|
parseFloat(values[0]),
|
||||||
@ -128,40 +128,40 @@ function loadMtl(mtlPath, options) {
|
|||||||
parseFloat(values[2]),
|
parseFloat(values[2]),
|
||||||
1.0
|
1.0
|
||||||
];
|
];
|
||||||
} else if (/^Ns /i.test(line)) {
|
} else if (/^Ns\s+/i.test(line)) {
|
||||||
value = line.substring(3).trim();
|
value = line.substring(3).trim();
|
||||||
material.specularShininess = parseFloat(value);
|
material.specularShininess = parseFloat(value);
|
||||||
} else if (/^d /i.test(line)) {
|
} else if (/^d\s+/i.test(line)) {
|
||||||
value = line.substring(2).trim();
|
value = line.substring(2).trim();
|
||||||
material.alpha = correctAlpha(parseFloat(value));
|
material.alpha = correctAlpha(parseFloat(value));
|
||||||
} else if (/^Tr /i.test(line)) {
|
} else if (/^Tr\s+/i.test(line)) {
|
||||||
value = line.substring(3).trim();
|
value = line.substring(3).trim();
|
||||||
material.alpha = correctAlpha(1.0 - parseFloat(value));
|
material.alpha = correctAlpha(1.0 - parseFloat(value));
|
||||||
} else if (/^map_Ka /i.test(line)) {
|
} else if (/^map_Ka\s+/i.test(line)) {
|
||||||
if (!defined(overridingAmbientTexture)) {
|
if (!defined(overridingAmbientTexture)) {
|
||||||
material.ambientTexture = normalizeTexturePath(line.substring(7).trim(), mtlDirectory);
|
material.ambientTexture = normalizeTexturePath(line.substring(7).trim(), mtlDirectory);
|
||||||
}
|
}
|
||||||
} else if (/^map_Ke /i.test(line)) {
|
} else if (/^map_Ke\s+/i.test(line)) {
|
||||||
if (!defined(overridingEmissiveTexture)) {
|
if (!defined(overridingEmissiveTexture)) {
|
||||||
material.emissiveTexture = normalizeTexturePath(line.substring(7).trim(), mtlDirectory);
|
material.emissiveTexture = normalizeTexturePath(line.substring(7).trim(), mtlDirectory);
|
||||||
}
|
}
|
||||||
} else if (/^map_Kd /i.test(line)) {
|
} else if (/^map_Kd\s+/i.test(line)) {
|
||||||
if (!defined(overridingDiffuseTexture)) {
|
if (!defined(overridingDiffuseTexture)) {
|
||||||
material.diffuseTexture = normalizeTexturePath(line.substring(7).trim(), mtlDirectory);
|
material.diffuseTexture = normalizeTexturePath(line.substring(7).trim(), mtlDirectory);
|
||||||
}
|
}
|
||||||
} else if (/^map_Ks /i.test(line)) {
|
} else if (/^map_Ks\s+/i.test(line)) {
|
||||||
if (!defined(overridingSpecularTexture)) {
|
if (!defined(overridingSpecularTexture)) {
|
||||||
material.specularTexture = normalizeTexturePath(line.substring(7).trim(), mtlDirectory);
|
material.specularTexture = normalizeTexturePath(line.substring(7).trim(), mtlDirectory);
|
||||||
}
|
}
|
||||||
} else if (/^map_Ns /i.test(line)) {
|
} else if (/^map_Ns\s+/i.test(line)) {
|
||||||
if (!defined(overridingSpecularShininessTexture)) {
|
if (!defined(overridingSpecularShininessTexture)) {
|
||||||
material.specularShininessTexture = normalizeTexturePath(line.substring(7).trim(), mtlDirectory);
|
material.specularShininessTexture = normalizeTexturePath(line.substring(7).trim(), mtlDirectory);
|
||||||
}
|
}
|
||||||
} else if (/^map_Bump /i.test(line)) {
|
} else if (/^map_Bump\s+/i.test(line)) {
|
||||||
if (!defined(overridingNormalTexture)) {
|
if (!defined(overridingNormalTexture)) {
|
||||||
material.normalTexture = normalizeTexturePath(line.substring(9).trim(), mtlDirectory);
|
material.normalTexture = normalizeTexturePath(line.substring(9).trim(), mtlDirectory);
|
||||||
}
|
}
|
||||||
} else if (/^map_d /i.test(line)) {
|
} else if (/^map_d\s+/i.test(line)) {
|
||||||
if (!defined(overridingAlphaTexture)) {
|
if (!defined(overridingAlphaTexture)) {
|
||||||
material.alphaTexture = normalizeTexturePath(line.substring(6).trim(), mtlDirectory);
|
material.alphaTexture = normalizeTexturePath(line.substring(6).trim(), mtlDirectory);
|
||||||
}
|
}
|
||||||
|
@ -42,10 +42,11 @@ 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)
|
||||||
const vertexPattern = /v( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // v float float float
|
const vertexPattern = /v(\s+[\d|\.|\+|\-|e|E]+)(\s+[\d|\.|\+|\-|e|E]+)(\s+[\d|\.|\+|\-|e|E]+)/; // v float float float
|
||||||
const normalPattern = /vn( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vn float float float
|
const normalPattern = /vn(\s+[\d|\.|\+|\-|e|E]+)(\s+[\d|\.|\+|\-|e|E]+)(\s+[\d|\.|\+|\-|e|E]+)/; // vn float float float
|
||||||
const uvPattern = /vt( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vt float float
|
const uvPattern = /vt(\s+[\d|\.|\+|\-|e|E]+)(\s+[\d|\.|\+|\-|e|E]+)/; // vt float float
|
||||||
const facePattern = /(-?\d+)\/?(-?\d*)\/?(-?\d*)/g; // for any face format "f v", "f v/v", "f v//v", "f v/v/v"
|
const facePattern = /(-?\d+)\/?(-?\d*)\/?(-?\d*)/g; // for any face format "f v", "f v/v", "f v//v", "f v/v/v"
|
||||||
|
const faceStartPattern = /f\s+/;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse an obj file.
|
* Parse an obj file.
|
||||||
@ -356,11 +357,11 @@ function loadObj(objPath, options) {
|
|||||||
// Because face lines can contain n vertices, we use a line buffer in case the face data spans multiple lines.
|
// Because face lines can contain n vertices, we use a line buffer in case the face data spans multiple lines.
|
||||||
// If there's a line continuation don't create face yet
|
// If there's a line continuation don't create face yet
|
||||||
if (line.slice(-1) === '\\') {
|
if (line.slice(-1) === '\\') {
|
||||||
lineBuffer += line.substring(0, line.length-1);
|
lineBuffer += line.slice(0, -1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lineBuffer += line;
|
lineBuffer += line;
|
||||||
if (lineBuffer.substring(0, 2) === 'f ') {
|
if (faceStartPattern.test(lineBuffer)) {
|
||||||
while ((result = facePattern.exec(lineBuffer)) !== null) {
|
while ((result = facePattern.exec(lineBuffer)) !== null) {
|
||||||
faceVertices.push(result[0]);
|
faceVertices.push(result[0]);
|
||||||
facePositions.push(result[1]);
|
facePositions.push(result[1]);
|
||||||
@ -402,7 +403,7 @@ function loadObj(objPath, options) {
|
|||||||
function getMtlPaths(mtllibLine) {
|
function getMtlPaths(mtllibLine) {
|
||||||
// Handle paths with spaces. E.g. mtllib my material file.mtl
|
// Handle paths with spaces. E.g. mtllib my material file.mtl
|
||||||
const mtlPaths = [];
|
const mtlPaths = [];
|
||||||
const splits = mtllibLine.split(' ');
|
const splits = mtllibLine.split(/\s/);
|
||||||
const length = splits.length;
|
const length = splits.length;
|
||||||
let startIndex = 0;
|
let startIndex = 0;
|
||||||
for (let i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
|
12
specs/data/box-tabs/box-tabs.mtl
Normal file
12
specs/data/box-tabs/box-tabs.mtl
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Blender MTL File: 'None'
|
||||||
|
# Material Count: 1
|
||||||
|
|
||||||
|
newmtl Material
|
||||||
|
Ns 96.078431
|
||||||
|
Ka 0.100000 0.000000 0.000000
|
||||||
|
Kd 0.640000 0.640000 0.640000
|
||||||
|
Ks 0.500000 0.500000 0.500000
|
||||||
|
Ke 0.000000 0.000000 0.100000
|
||||||
|
Ni 1.000000
|
||||||
|
d 1.000000
|
||||||
|
illum 2
|
46
specs/data/box-tabs/box-tabs.obj
Normal file
46
specs/data/box-tabs/box-tabs.obj
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#Blender v2.78 (sub 0) OBJ File: ''
|
||||||
|
# www.blender.org
|
||||||
|
mtllib box-tabs.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
|
||||||
|
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
|
||||||
|
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
|
@ -10,6 +10,7 @@ const clone = Cesium.clone;
|
|||||||
const RuntimeError = Cesium.RuntimeError;
|
const RuntimeError = Cesium.RuntimeError;
|
||||||
|
|
||||||
const objPath = 'specs/data/box/box.obj';
|
const objPath = 'specs/data/box/box.obj';
|
||||||
|
const objTabsPath = 'specs/data/box-tabs/box-tabs.obj';
|
||||||
const objNormalsPath = 'specs/data/box-normals/box-normals.obj';
|
const objNormalsPath = 'specs/data/box-normals/box-normals.obj';
|
||||||
const objUvsPath = 'specs/data/box-uvs/box-uvs.obj';
|
const objUvsPath = 'specs/data/box-uvs/box-uvs.obj';
|
||||||
const objPositionsOnlyPath = 'specs/data/box-positions-only/box-positions-only.obj';
|
const objPositionsOnlyPath = 'specs/data/box-positions-only/box-positions-only.obj';
|
||||||
@ -102,6 +103,25 @@ describe('loadObj', () => {
|
|||||||
expect(primitive.material).toBe('Material');
|
expect(primitive.material).toBe('Material');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('loads obj with tabs', async () => {
|
||||||
|
const data = await loadObj(objTabsPath, options);
|
||||||
|
const primitives = getPrimitives(data);
|
||||||
|
const primitive = primitives[0];
|
||||||
|
|
||||||
|
expect(primitive.positions.length / 3).toBe(24);
|
||||||
|
expect(primitive.normals.length / 3).toBe(24);
|
||||||
|
expect(primitive.uvs.length / 2).toBe(24);
|
||||||
|
expect(primitive.indices.length).toBe(36);
|
||||||
|
expect(primitive.material).toBe('Material');
|
||||||
|
|
||||||
|
const material = data.materials[0];
|
||||||
|
const pbr = material.pbrMetallicRoughness;
|
||||||
|
expect(pbr.baseColorFactor).toEqual([0.64, 0.64, 0.64, 1.0]);
|
||||||
|
expect(pbr.metallicFactor).toBe(0.0);
|
||||||
|
expect(CesiumMath.equalsEpsilon(pbr.roughnessFactor, 0.903921569, CesiumMath.EPSILON7)).toBe(true);
|
||||||
|
expect(material.emissiveFactor).toEqual([0.0, 0.0, 0.1]);
|
||||||
|
});
|
||||||
|
|
||||||
it('loads obj with normals', async () => {
|
it('loads obj with normals', async () => {
|
||||||
const data = await loadObj(objNormalsPath, options);
|
const data = await loadObj(objNormalsPath, options);
|
||||||
const primitive = getPrimitives(data)[0];
|
const primitive = getPrimitives(data)[0];
|
||||||
|
Loading…
Reference in New Issue
Block a user