gsots3d
Version:
Getting S**t On The Screen in 3D. A library for doing 3D graphics in the browser.
201 lines (200 loc) • 4.76 kB
JavaScript
// src/parsers/mtl-parser.ts
function parseMTL(mtlFile) {
const materials = /* @__PURE__ */ new Map();
let material = {};
const keywords = {
newmtl(_, unparsedArgs) {
material = {};
materials.set(unparsedArgs, material);
},
Ns(parts) {
material.ns = parseFloat(parts[0]);
},
Ka(parts) {
material.ka = parts.map(parseFloat);
},
Kd(parts) {
material.kd = parts.map(parseFloat);
},
Ks(parts) {
material.ks = parts.map(parseFloat);
},
// This is a non-standard addition, but semi-official
Ke(parts) {
material.ke = parts.map(parseFloat);
},
Ni() {
},
d(parts) {
material.d = parseFloat(parts[0]);
},
illum(parts) {
material.illum = parseInt(parts[0]);
},
map_Kd(_, unparsedArgs) {
material.texDiffuse = unparsedArgs;
},
map_Ks(_, unparsedArgs) {
material.texSpecular = unparsedArgs;
},
map_bump(_, unparsedArgs) {
material.texNormal = unparsedArgs;
},
map_Bump(_, unparsedArgs) {
material.texNormal = unparsedArgs;
}
};
const keywordRE2 = /(\w*)(?: )*(.*)/;
const lines = mtlFile.split("\n");
for (let lineNo = 0; lineNo < lines.length; ++lineNo) {
const line = lines[lineNo].trim();
if (line === "" || line.startsWith("#")) {
continue;
}
const m = keywordRE2.exec(line);
if (!m) {
continue;
}
const [, keyword, unparsedArgs] = m;
const parts = line.split(/\s+/).slice(1);
const handler = keywords[keyword];
if (!handler) {
continue;
}
handler(parts, unparsedArgs);
}
return materials;
}
// src/parsers/obj-parser.ts
var keywordRE = /(\w*)(?: )*(.*)/;
function parseOBJ(objFile, flipUV) {
const lines = objFile.split("\n");
const objPositions = [[0, 0, 0]];
const objTexcoords = [[0, 0]];
const objNormals = [[0, 0, 0]];
const objVertexData = [objPositions, objTexcoords, objNormals];
let triangles = 0;
let webglVertexData = [
[],
// Position
[],
// Texcoord
[]
// Normal
];
const geometries = Array();
let geometry = {};
let material = "__default";
const materialLibs = Array();
const keywords = {
v(parts) {
objPositions.push(parts.map(parseFloat));
},
vn(parts) {
objNormals.push(parts.map(parseFloat));
},
vt(parts) {
if (flipUV) {
objTexcoords.push([parseFloat(parts[0]), 1 - parseFloat(parts[1])]);
} else {
objTexcoords.push([parseFloat(parts[0]), parseFloat(parts[1])]);
}
},
f(parts) {
triangles++;
setGeometry();
const numTriangles = parts.length - 2;
for (let tri = 0; tri < numTriangles; ++tri) {
addVertex(parts[0]);
addVertex(parts[tri + 1]);
addVertex(parts[tri + 2]);
}
},
usemtl(_, unparsedArgs) {
material = unparsedArgs;
newGeometry();
},
mtllib(_, unparsedArgs) {
materialLibs.push(unparsedArgs);
},
// Not used, but suppress warnings
s() {
return;
},
o() {
return;
},
g() {
return;
},
l() {
return;
}
};
function addVertex(vert) {
const ptn = vert.split("/");
ptn.forEach((objIndexStr, i) => {
if (!objIndexStr) {
return;
}
const objIndex = parseInt(objIndexStr);
const index = objIndex + (objIndex >= 0 ? 0 : objVertexData[i].length);
webglVertexData[i].push(...objVertexData[i][index]);
});
}
function newGeometry() {
if (geometry.material) {
geometry = {};
}
}
function setGeometry() {
if (!geometry.material) {
const position = [];
const texcoord = [];
const normal = [];
webglVertexData = [position, texcoord, normal];
geometry = {
material,
data: {
position,
texcoord,
normal
}
};
geometries.push(geometry);
}
}
for (let lineNo = 0; lineNo < lines.length; ++lineNo) {
const line = lines[lineNo].trim();
if (line === "" || line.startsWith("#")) {
continue;
}
const m = keywordRE.exec(line);
if (!m) {
continue;
}
const [, keyword, unparsedArgs] = m;
const parts = line.split(/\s+/).slice(1);
const handler = keywords[keyword];
if (!handler) {
console.warn("unhandled keyword:", keyword, "at line", lineNo + 1);
continue;
}
handler(parts, unparsedArgs);
}
for (const g of geometries) {
if (g.data.texcoord && g.data.texcoord.length <= 0) {
delete g.data.texcoord;
}
}
return {
matLibNames: materialLibs,
geometries,
triangles
};
}
export {
parseMTL,
parseOBJ
};
//# sourceMappingURL=index.js.map