Brakebein / node-three-gltf

Use three.js GLTFLoader in a Node.js environment
MIT License
25 stars 8 forks source link

setMeshoptDecoder must be called before loading compressed files #13

Open fax1ty opened 6 months ago

fax1ty commented 6 months ago
import {
  DRACOLoader,
  GLTFLoader,
  loadGltf as loadAsync,
} from "node-three-gltf";
import { MeshoptDecoder } from "three-stdlib";

export const loadGltf = async (url: string) => {
  const gltf = new GLTFLoader();
  const draco = new DRACOLoader();
  gltf.setDRACOLoader(draco);
  gltf.setMeshoptDecoder(MeshoptDecoder);

  return await loadAsync(url);
};

results in

Error: THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files

How can I load compressed gltfs?

Brakebein commented 6 months ago

I found out that the MeshoptDecoder from three-stdlib is exported differently than from three/examples/libs. three-stdlib returns a function, and three/examples/libs returns this function already executed.

So you might need to try:

gltf.setMeshoptDecoder(MeshoptDecoder());

https://github.com/mrdoob/three.js/blob/master/examples/jsm/libs/meshopt_decoder.module.js https://github.com/pmndrs/three-stdlib/blob/main/src/libs/MeshoptDecoder.ts

fax1ty commented 6 months ago

@Brakebein Nope( Same error

player.glbplayer-draco.glbplayer-meshopt.glb

Brakebein commented 6 months ago

Now, I see the problem: you are using this small utility function loadGtlf. However, this doesn't set the MeshoptDecoder. You need to use the load method of the GLTFLoader you've already instantiated. So, instead of return await loadAsync(url); you need to call return await gltf.loadAsync(url); (and omit the import loadGltf as loadAsync).

That's how it worked for me:

import { GLTFLoader } from 'node-three-gltf';
import { MeshoptDecoder } from 'three-stdlib';

const loader = new GLTFLoader();
loader.setMeshoptDecoder(MeshoptDecoder());
loader.load('player-meshopt.glb', (gltf) => {
  console.log(gltf);
}, null, (err) => {
  console.error(err);
});
fax1ty commented 6 months ago
import { DRACOLoader, GLTFLoader } from "node-three-gltf";
import { type GLTF, MeshoptDecoder } from "three-stdlib";

export const loadGltf = async (url: string) => {
  const loader = new GLTFLoader();
  const draco = new DRACOLoader();
  const meshopt = MeshoptDecoder();
  loader.setDRACOLoader(draco);
  loader.setMeshoptDecoder(meshopt);

  const gltf = await loader.loadAsync(url);

  return gltf as GLTF;
};

Worked as well. Big thanks, @Brakebein

fax1ty commented 6 months ago

It may be worth nothing that node-three-gltf/loadGltf does not support meshopt out of the box You may specify this in the Readme file

Brakebein commented 6 months ago

Well, the readme states that it instantiates GLTFLoader and DRACOLoader, but doesn't mention anything else.

// there is also a small utility function that instantiates GLTFLoader and DRACOLoader

Fact is that I only worked with draco-compressed gltf files so far, I haven't done yet anything with the MeshoptDecoder. So maybe, I will update the readme in this regard next time.