@loaders.gl/obj
Version:
Framework-independent loader for the OBJ format
69 lines (68 loc) • 2.19 kB
JavaScript
import { getMeshBoundingBox } from '@loaders.gl/schema';
import { parseOBJMeshes } from "./parse-obj-meshes.js";
import { getOBJSchema } from "./get-obj-schema.js";
export function parseOBJ(text, options) {
const { meshes } = parseOBJMeshes(text);
// @ts-expect-error
const vertexCount = meshes.reduce((s, mesh) => s + mesh.header.vertexCount, 0);
// TODO - render objects separately
const attributes = mergeAttributes(meshes, vertexCount);
const header = {
vertexCount,
// @ts-ignore Need to export Attributes type
boundingBox: getMeshBoundingBox(attributes)
};
const schema = getOBJSchema(attributes, {
mode: 4,
boundingBox: header.boundingBox
});
return {
// Data return by this loader implementation
loaderData: {
header: {}
},
// Normalised data
schema,
header,
mode: 4, // TRIANGLES
topology: 'point-list',
attributes
};
}
// eslint-disable-next-line max-statements
function mergeAttributes(meshes, vertexCount) {
const positions = new Float32Array(vertexCount * 3);
let normals;
let colors;
let uvs;
let i = 0;
for (const mesh of meshes) {
const { POSITION, NORMAL, COLOR_0, TEXCOORD_0 } = mesh.attributes;
positions.set(POSITION.value, i * 3);
if (NORMAL) {
normals = normals || new Float32Array(vertexCount * 3);
normals.set(NORMAL.value, i * 3);
}
if (COLOR_0) {
colors = colors || new Float32Array(vertexCount * 3);
colors.set(COLOR_0.value, i * 3);
}
if (TEXCOORD_0) {
uvs = uvs || new Float32Array(vertexCount * 2);
uvs.set(TEXCOORD_0.value, i * 2);
}
i += POSITION.value.length / 3;
}
const attributes = {};
attributes.POSITION = { value: positions, size: 3 };
if (normals) {
attributes.NORMAL = { value: normals, size: 3 };
}
if (colors) {
attributes.COLOR_0 = { value: colors, size: 3 };
}
if (uvs) {
attributes.TEXCOORD_0 = { value: uvs, size: 2 };
}
return attributes;
}