How to use gltfloader in nodejs

i need to use gltfloader in nodejs,i want to get glb model and deal with the glb to get some data and output this data in nodejs,i find create mesh is ok,but loader model cannot success ,i try something but not good,Anybody has a working solution?or
recommend me some example about threejs use gltfloader in nodejs

//glb model: t1.glb  
//three r145  type:module
import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
const scene = new THREE.Scene();
var geometry = new THREE.BoxGeometry(100, 100, 100); 
var material = new THREE.MeshLambertMaterial({
	color: 0x0000ff
}); 
var mesh = new THREE.Mesh(geometry, material);
//success
scene.add(mesh); 

//how to scene.add(glb model?)




see doc

see examples

i try to load with gltfloader.parse:

let content=fs.readFileSync(file);
const gltfloader=new GLTFLoader();
gltfloader.parse(content,'',function(gltf){
	scene.add(gltf.scene);
},function(){
	console.log('model load error')
});

but put:

undefined:1
glTF
^

SyntaxError: Unexpected token g in JSON at position 0
    at JSON.parse (<anonymous>)
    at GLTFLoader.parse (file:///D:/work/20221012/node_modules/three/examples/jsm/loaders/GLTFLoader.js:315:21)
    at file:///D:/work/20221012/test.js:22:12
    at ModuleJob.run (node:internal/modules/esm/module_job:198:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:385:24)
    at async loadESM (node:internal/process/esm_loader:88:5)
    at async handleMainPromise (node:internal/modules/run_main:61:12)

the problem also happend in my project,how to give a resolution.

it’s not easily possible. gltfloader relies on web xhr fetch requests and web workers to function. i’ve seen people try to emulate this under node but i haven’t seen something that actually works.

if with “some data” you mean structural data there could be a way. i have forked the loader here GitHub - pmndrs/gltfjsx: 🎮 Turns GLTFs into JSX components this is a node tool, it allows me to read out all structural data, the scene, materials, all props, positions, userData, etc, i have removed everything that had to do with texture and geometry buffers to make it work. the loader is under /src/bin

there is also the GitHub - donmccurdy/glTF-Transform: glTF 2.0 SDK for JavaScript, TypeScript, and Node.js. project. it can parse and process gltfs under node. this is most likely the best solution but i have only ever used the transforms, i haven’t used it to parse files or looked into the code to see how it works. @donmccurdy has made it.

last but not least, if you want to actually display the results in some way i would suggest you use puppeteer, a headless browser environment for node.

I don’t know your use case, but if you do not need textures, edit the source to disable the texture loading stuff should do the trick.
Otherwise, and other use case maybe, try a different approach with https://gltf-transform.donmccurdy.com/

glTF Transform is a good choice if you want to read/edit/write glTF files in a Node.js environment. It has prebuilt functions for many complex operations (e.g. Draco compression, texture resizing) and a scripting API to do anything more custom. Works in Web, Node.js, and CLI.

But if you’re trying to load the glTF file into native three.js objects like THREE.GLTFLoader would create (THREE.Mesh, THREE.Group, etc.), … things are harder. three.js uses many web APIs, Node.js doesn’t have many of the APIs we need, and so there’s no there’s no simple way to get all three.js features working in Node.js. Getting your project to work will depend heavily on which three.js features you plan to use.

Hello,

You can try this repo.
It’s basically THREE but they removed WebAPIs dependencies.

I tested it for .glb and it works well.

1 Like

I managed to strip down the code from the project @petitglacon has provided.

By adding this polyfill code

class ProgressEvent {
    constructor(type, progressEventInit = {}) {
        this.type = type;
        this.lengthComputable = progressEventInit.lengthComputable || false;
        this.loaded = progressEventInit.loaded || 0;
        this.total = progressEventInit.total || 0;
    }
}

global.ProgressEvent ??= ProgressEvent;
global.self ??= global;

In my case, Even if the GLTF file has texture.
It is still successfully loaded into threejs objects but without textures.
This is sufficient for me to do some calculations stuff on the server.

Version:
three: 0.152.2
node: 19

4 Likes

Hey Guys,
I was also looking for a solution. The solution from @benzsuankularb was already helpful, but there were still problems with the exporter that I had to solve.

I finally found three-stdlib https://github.com/pmndrs/three-stdlib?tab=readme-ov-file. Which has a working GLTFExporter and GLTFLoader in Node.js.

npm install three-stdlib and then import {GLTFLoader, GLTFExporter} from "three-stdlib"; instead of threejs/examples/jsm/...

Edit: sorry, after clean up I notice I still need the polyfill code above for the loader, but in combination with three-stdlib I got a working GLTFExporter and GLTFLoader in Node.js.

1 Like

More gotcha here.

Using GLTFExporter with a large attribute will cause the stack exceed error.
This happened in Node and not the browser.

You could solve this by exporting to GLB instead.

new GLTFExport().parseAsync(scene, { binary: true })