pmndrs / gltfjsx

🎮 Turns GLTFs into JSX components
https://gltf.pmnd.rs
MIT License
4.42k stars 290 forks source link

Unexpected token g in JSON when using GLTFStructureLoader #150

Open dottodot opened 2 years ago

dottodot commented 2 years ago

I was hoping I'd be able to use the GLTFStructureLoader in a node js app using the following

const { GLTFStructureLoader } = require("@react-three/gltfjsx");
const fs = require("fs/promises");
const loader = new GLTFStructureLoader();

async function loadModel() {
  const data = await fs.readFile("./model.glb");

  const { scene } = await new Promise((res) =>
    loader.parse(data, "", res)
  );
  console.log(scene);
}

but this causes an error of

SyntaxError: Unexpected token g in JSON at position 0
    at JSON.parse (<anonymous>)
    at GLTFLoader.parse (/nodejs/node_modules/@react-three/gltfjsx/src/bin/GLTFLoader.js:145:23)
    at /nodejs/index.js:10:12
    at new Promise (<anonymous>)
    at loadModel (/nodejs/index.js:9:27)

however using npx gltfjsx on the same model is fine.

hannesuw commented 1 year ago

+1

ajitStephen commented 1 year ago

+1

ashleymvanduzer commented 1 year ago

+1

donmccurdy commented 1 year ago

The problem here may be passing a Buffer or Uint8Array into the parse() method, when an ArrayBuffer is required. To do the conversion:

const arrayBuffer = data.buffer.slice( data.byteOffset, data.byteLength );

loader.parse( arrayBuffer, '', callback );
ashleymvanduzer commented 1 year ago

@donmccurdy thanks for the suggestion! excited to give that a shot.

ashleymvanduzer commented 1 year ago

@donmccurdy thanks so much, that did the trick.

ashleymvanduzer commented 1 year ago

@donmccurdy The solution works as you suggested with non gltfjsx transformed models, again so many thanks for the tip. Though I recently used gltfjsx with the transform flag on a big chunk of the models I am using to bring bundle size down for the project I am working on. But now, when I try to pass one of these transformed models, I run into the error: ` THREE.GLTFLoader: No DRACOLoader instance provided.

  91 |   //@ts-ignore
  92 |   const {scene} = await new Promise((resolve) => {
> 93 |     loader.parse(arrayBuffer, '', resolve);
     |            ^
  94 |   }
  95 | );

`

So I followed the error message and passed a draco loader to the GLTFStructureLoader, and the output becomes:

` ReferenceError: Request is not defined

  at FileLoader.load (node_modules/three/build/three.cjs:28302:15)
  at node_modules/three-stdlib/index.cjs.js:1:1223275
  at vh._loadLibrary (node_modules/three-stdlib/index.cjs.js:1:1223252)
  at vh._initDecoder (node_modules/three-stdlib/index.cjs.js:1:1223553)
  at vh._getWorker (node_modules/three-stdlib/index.cjs.js:1:1223995)
  at vh.decodeGeometry (node_modules/three-stdlib/index.cjs.js:1:1222541)
  at vh.decodeDracoFile (node_modules/three-stdlib/index.cjs.js:1:1222076)
  at node_modules/@react-three/gltfjsx/src/bin/GLTFLoader.js:612:21
  at node_modules/@react-three/gltfjsx/src/bin/GLTFLoader.js:611:14
      at async Promise.all (index 0)
      at async Promise.all (index 1)
      at async Promise.all (index 0)
      at async Promise.all (index 0)

`

Sorry to bother you further, but if you happen to have some time and any insight into why this may be happening, I'd really appreciate hearing your thoughts on this.

donmccurdy commented 1 year ago

It might be best to file a bug, attach a model that demonstrates the issue, and share any other details like the version of Node.js you're using. Using gltfjsx on a Draco-compressed model does seem to be working correctly for me.

ashleymvanduzer commented 1 year ago

@donmccurdy Much appreciated, I'll go ahead and do that.