@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
241 lines • 19.4 kB
JavaScript
import { forEachLine } from "../for-each-line.js";
import { TgdVec3 } from "./../../math/index.js";
import { TgdGeometry } from "./../../geometry/index.js";
/**
* This [Wavefront](https://en.wikipedia.org/wiki/Wavefront_.obj_file)
* parser only finds the object name,
* the vertices coords, the normals and the UVs.
*
* - There can be only one object per file.
* - Normals and UVs are optional.
* - All faces **must** be triangles.
*
* To export an obj file from blender, please use the following options:
*
* - Forward axis: **Y**
* - Up axis: **Z**
* - Object / Apply Modifiers: **True**
* - Geometry / UV Coordinates: **True**
* - Geometry / Normals: **True**
* - Geometry / Triangulated Mesh: **True**
*/
export class TgdParserMeshWavefront {
constructor(content) {
this.name = "Mesh";
this.attPosition = [];
this.attNormal = [];
this.attUV = [];
/**
* Three consecutive elements define a triangle.
* An element is a index on the attributes array.
*/
this.elements = [];
this.elementIndex = 0;
/**
* The key is `${pointIndex}/${normalIndex}/${uvIndex}`.
* The value is the index of the vertex (used in `elements`).
*/
this.mapVertices = new Map();
/**
* A point ins not a vertex, but just a position in space
* that can be used by several different vertices.
* That's the case for faces sharing a vertex but having different
* normals. A vertex is made of a position, a normal and an uv.
*/
this.points = [];
/**
* A item of this array can be shared by different vertices.
*/
this.normals = [];
/**
* List of vertices per face.
* The vertices are represented by the index of the attribute.
*/
this.verticesPerTriangle = [];
/**
* Here "normal" is an index on `this.normals` array.
*/
this.normalPerTriangle = [];
/**
* The vertices are indexed per attribute.
* The triangles are represented by indexes from `this.normalPerTriangle`.
*/
this.trianglesPerVertex = [];
/**
* A item of this array can be shared by different vertices.
*/
this.uvs = [];
this.onObject = (name) => {
this.name = name;
};
this.onVertex = (x, y, z) => {
this.points.push([x, y, z]);
};
this.onNormal = (x, y, z) => {
this.normals.push([x, y, z]);
};
this.onTexture = (u, v) => {
this.uvs.push([u, v]);
};
this.onFace = (vertices) => {
var _a;
var _b;
if (vertices.length !== 3)
throw new Error("We can only deal with triangles!");
const triangle = vertices.map(vertex => this.getElem(vertex));
this.elements.push(...triangle);
this.normalPerTriangle.push(new TgdVec3(0, 0, 0));
this.verticesPerTriangle.push(triangle);
const triangleIndex = this.normalPerTriangle.length - 1;
for (const vertexIndex of triangle) {
(_a = (_b = this.trianglesPerVertex)[vertexIndex]) !== null && _a !== void 0 ? _a : (_b[vertexIndex] = []);
this.trianglesPerVertex[vertexIndex].push(triangleIndex);
}
};
/**
* Return the index of the vertex for the triplet
* point/normal/uv.
*/
this.getElem = (triangleSummit) => {
var _a;
const k = this.key(triangleSummit);
const index = (_a = this.mapVertices.get(k)) !== null && _a !== void 0 ? _a : -1;
if (index > -1)
return index;
const [vx, vy, vz] = this.points[triangleSummit.vertex];
this.attPosition.push(vx, vy, vz);
if (typeof triangleSummit.normal === "number") {
const [nx, ny, nz] = this.normals[triangleSummit.normal];
this.attNormal.push(nx, ny, nz);
}
if (typeof triangleSummit.uv === "number") {
const [tx, ty] = this.uvs[triangleSummit.uv];
this.attUV.push(tx, ty);
}
this.mapVertices.set(k, this.elementIndex);
return this.elementIndex++;
};
this.reset();
const { onVertex, onNormal, onTexture, onFace, onObject } = this;
parse(content, { onVertex, onNormal, onTexture, onFace, onObject });
}
makeGeometry({ computeNormals, } = {}) {
const options = {
attPosition: {
name: "POSITION",
data: new Float32Array(this.attPosition),
},
computeNormalsIfMissing: computeNormals,
};
if (this.attNormal.length > 0) {
options.attNormal = {
name: "NORMAL",
data: new Float32Array(this.attNormal),
};
}
if (this.attUV.length > 0) {
options.attUV = {
name: "TEXTCOORDS_0",
data: new Float32Array(this.attUV),
};
}
const { elements, elementIndex } = this;
if (elementIndex <= 256) {
options.elements = new Uint8Array(elements);
}
else if (elementIndex <= 0x10000) {
options.elements = new Uint16Array(elements);
}
else {
options.elements = new Uint32Array(elements);
}
return TgdGeometry.make(options);
}
computeNormals() {
const A = new TgdVec3();
const B = new TgdVec3();
const C = new TgdVec3();
for (const [triangleIndex, normal,] of this.normalPerTriangle.entries()) {
const [v0, v1, v2] = this.verticesPerTriangle[triangleIndex];
this.readVertexInto(v0, A);
this.readVertexInto(v1, B).subtract(A);
this.readVertexInto(v2, C).subtract(A);
normal.from(B.cross(C).normalize());
}
this.attNormal = [];
for (let elementIndex = 0; elementIndex < this.elementIndex; elementIndex++) {
const normal = new TgdVec3(0, 0, 0);
for (const triIndex of this.trianglesPerVertex[elementIndex])
normal.add(this.normalPerTriangle[triIndex]);
const [nx, ny, nz] = normal.normalize();
this.attNormal.push(nx, ny, nz);
}
}
reset() {
this.name = "Mesh";
this.attPosition = [];
this.attNormal = [];
this.attUV = [];
this.elements = [];
this.elementIndex = 0;
this.points = [];
this.normals = [];
this.verticesPerTriangle = [];
this.trianglesPerVertex = [];
this.normalPerTriangle = [];
this.uvs = [];
this.mapVertices.clear();
this.mapVertices.clear();
}
key(v) {
return `${v.vertex}/${v.normal}`;
}
readVertexInto(index, target) {
const P = this.attPosition;
const k = index * 3;
target.reset(P[k + 0], P[k + 1], P[k + 2]);
return target;
}
}
function parse(content, options = {}) {
const { onVertex, onNormal, onTexture, onFace, onObject } = options;
for (const fullLine of forEachLine(content)) {
const line = fullLine.trimStart();
if (onVertex && line.startsWith("v ")) {
const vertex = line.slice("v ".length).split(" ").map(Number);
if (isVector3(vertex))
onVertex(...vertex);
}
else if (onFace && line.startsWith("f ")) {
onFace(line
.slice("f ".length)
.split(" ")
// Warning! We need to remove 1 to the index.
.map(face => {
const [v, t, n] = face.split("/");
return {
vertex: Number(v) - 1,
normal: n ? Number(n) - 1 : undefined,
uv: t ? Number(t) - 1 : undefined,
};
}));
}
else if (onNormal && line.startsWith("vn ")) {
const normal = line.slice("vn ".length).split(" ").map(Number);
if (isVector3(normal))
onNormal(...normal);
}
else if (onTexture && line.startsWith("vt ")) {
const [u, v, w] = line.slice("vt ".length).split(" ").map(Number);
onTexture(u, v, w);
}
else if (onObject && line.startsWith("o ")) {
const name = line.slice("o ".length);
onObject(name);
}
}
}
function isVector3(data) {
return data.length === 3;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2F2ZWZyb250LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3BhcnNlci9tZXNoL3dhdmVmcm9udC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sa0JBQWtCLENBQUE7QUFDOUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUNuQyxPQUFPLEVBQUUsV0FBVyxFQUF1QixNQUFNLGVBQWUsQ0FBQTtBQVFoRTs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFDSCxNQUFNLE9BQU8sc0JBQXNCO0lBK0MvQixZQUFZLE9BQWU7UUE5Q25CLFNBQUksR0FBRyxNQUFNLENBQUE7UUFDYixnQkFBVyxHQUFhLEVBQUUsQ0FBQTtRQUMxQixjQUFTLEdBQWEsRUFBRSxDQUFBO1FBQ3hCLFVBQUssR0FBYSxFQUFFLENBQUE7UUFDNUI7OztXQUdHO1FBQ0ssYUFBUSxHQUFhLEVBQUUsQ0FBQTtRQUV2QixpQkFBWSxHQUFHLENBQUMsQ0FBQTtRQUN4Qjs7O1dBR0c7UUFDYyxnQkFBVyxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFBO1FBQ3hEOzs7OztXQUtHO1FBQ0ssV0FBTSxHQUErQixFQUFFLENBQUE7UUFDL0M7O1dBRUc7UUFDSyxZQUFPLEdBQStCLEVBQUUsQ0FBQTtRQUNoRDs7O1dBR0c7UUFDSyx3QkFBbUIsR0FBZSxFQUFFLENBQUE7UUFDNUM7O1dBRUc7UUFDSyxzQkFBaUIsR0FBYyxFQUFFLENBQUE7UUFDekM7OztXQUdHO1FBQ0ssdUJBQWtCLEdBQWUsRUFBRSxDQUFBO1FBQzNDOztXQUVHO1FBQ0ssUUFBRyxHQUFlLEVBQUUsQ0FBQTtRQXdGWCxhQUFRLEdBQUcsQ0FBQyxJQUFZLEVBQUUsRUFBRTtZQUN6QyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQTtRQUNwQixDQUFDLENBQUE7UUFFZ0IsYUFBUSxHQUFHLENBQUMsQ0FBUyxFQUFFLENBQVMsRUFB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