libassimp
0.1.0

Convert an OBJ to GLB

Load an OBJ and its material asynchronously, configure processing, and write a GLB.

Open Markdown

1. Read the entry file

import { convert } from 'libassimp';
import { readFile, writeFile } from 'node:fs/promises';

const bytes = new Uint8Array(await readFile('cube.obj'));
const { files } = await convert({ name: 'cube.obj', bytes }, { to: 'glb' });
await writeFile(files[0].name, files[0].bytes);

The name selects the importer and establishes the base path for references.

2. Resolve the MTL only if Assimp requests it

import { convert } from 'libassimp';import { readFile } from 'node:fs/promises';const bytes = new Uint8Array(await readFile('cube.obj'));const { files } = await convert(  { name: 'cube.obj', bytes },  {    to: 'glb',    resolve: async (name) => {      try {        return new Uint8Array(await readFile(name));      } catch {        return undefined;      }    },  },);console.log(files[0].name);

Input

objcube.obj165 B
mtlcube.mtl55 B

Output

Preparing artifact…

Convert
Output
Files
WASM load

The callback may return bytes, absence, or a Promise of either. It is called once per exact requested name within the conversion.

3. Configure the typed pipeline

import { convert, defaultPostProcess } from 'libassimp';

const bytes = new Uint8Array();
const { files } = await convert(
  { name: 'cube.obj', bytes },
  {
    to: 'gltf',
    importOptions: { objUnitScaleToMeters: 1 },
    postProcess: [...defaultPostProcess, 'flipUvs'],
    exportOptions: { includeTargetNames: true },
  },
);

console.log(files.map(({ name }) => name));

Supplying postProcess replaces the default list; an empty array deliberately requests no steps. glTF output returns result.gltf followed by its sidecars. Every byte array is an owned copy.

On this page