Shantanu
Shantanu

Reputation: 319

How to use DRACOLoader with GLTFLoader in ReactJs?

I have a use case in which I am trying to load a GLTF file which is compressed using DRACO-Compression. I am able to run it using plain javascript but I am facing issues integrating the loader with ReactJs.

What I am doing:

The error I am getting - DracoDecoderModule is not defined

In my app, this is how I am importing:

  import DRACOLoader from './DRACOLoader'
  DRACOLoader.setDecoderPath('./draco/')

Upvotes: 18

Views: 21879

Answers (10)

emnul
emnul

Reputation: 3

If you're using Vite and you don't want to use a CDN you need to copy the three/examples/jsm/libs/draco/gltf/ folder into your static / public folder. Then you can set the path using the new URL(url, import.meta.url) method

// Imports
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js'

// Create loader
const dracoDecoderPath = new URL('./draco/gltf', import.meta.url).href
const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath(dracoDecoderPath + '/')
// This also works
//dracoLoader.setDecoderPath('draco/gltf/')

const gltfLoader = new GLTFLoader()
gltfLoader.setDRACOLoader(dracoLoader)

Upvotes: 0

Cinzia Nicoletti
Cinzia Nicoletti

Reputation: 305

This is what worked for me:

   const loader = new GLTFLoader();
   const dracoLoader = new DRACOLoader();
    
   dracoLoader.setDecoderPath('/node_modules/three/examples/jsm/libs/draco/');
    
   loader.setDRACOLoader( dracoLoader );

I hope it will be useful to you.

Upvotes: 0

Tommaso Iacolettig
Tommaso Iacolettig

Reputation: 21

It is recommended to use https://www.gstatic.com/draco/versioned/decoders/[version]/ as the decoder source directory, e.g.:

const draco = new DRACOLoader();
draco.setDecoderConfig({ type: 'js' });
draco.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/');

Using the versioned www.gstatic.com WASM and Javascript decoders is recommended since v1.4.1, as stated here.

Upvotes: 1

Ben
Ben

Reputation: 16689

I am using Webpack in a similar way to how Create React App uses it. Here is how I got the Draco decoder path working.

  1. In your app's public folder, create a new folder called draco.

  2. Download the four files found in the Three.js Draco Examples and move them into your public/draco folder.

  3. Use this code:

// Imports
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';

// Create a new DRACO loader (for decompressing compressed GLTF models)
const dracoLoader = new DRACOLoader();

// Set the DRACO loader's decoder path to the `public/draco` folder
// NB: You have to manually download and copy/paste the files from 
// https://github.com/mrdoob/three.js/tree/dev/examples/js/libs/draco/gltf
// into this folder.
dracoLoader.setDecoderPath('./draco/');

// Create a new GLTF loader
const gltfLoader = new GLTFLoader();

// Use the DRACO loader with the GLTF loader
gltfLoader.setDRACOLoader(dracoLoader);

Upvotes: 0

Bill O
Bill O

Reputation: 410

Perhaps another option (for React only).

I copied the three required files from node_modules to public, in a folder called 'draco'.

const gltfLoader = new GLTFLoader()
const dracoLoader = new DRACOLoader()  // allow for DRACO compression
dracoLoader.setDecoderPath(process.env.PUBLIC_URL + '/draco/')
gltfLoader.setDRACOLoader(dracoLoader)

Upvotes: 1

marrion luaka
marrion luaka

Reputation: 157

Relative paths won't work. One way to achieve this is by either hosting your draco_wasm_wrapper.js on like aws or something like that or you could try the following:

npm i -S three // make sure you have the latest threejs package v2 and up

Import your dependencies:

import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'

Create and configue your draco loader:

const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath('https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/js/libs/draco/'); // use a full url path

Create and configure your gltf loader:

const gltf = new GLTFLoader();
gltf.setDRACOLoader(dracoLoader);

// then you can load your glb file
const glbPath = 'your glb file'
gltf.load(glbPath, function(gltf) {
  console.log(gltf)
})

Upvotes: 8

arn
arn

Reputation: 171

It is recommended to use https://www.gstatic.com/draco/v1/decoders/ as the decoder source directory, e.g.:

const draco = new DRACOLoader();
draco.setDecoderConfig({ type: 'js' });
draco.setDecoderPath('https://www.gstatic.com/draco/v1/decoders/');

See example https://github.com/google/draco/tree/master/javascript/example.

Upvotes: 17

duhaime
duhaime

Reputation: 27611

None of the above worked directly for me on [email protected] so I used:

import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
import * as THREE from 'three';

// draco
const draco = new DRACOLoader()
draco.setDecoderPath('../node_modules/three/examples/js/libs/draco/gltf/');
draco.setDecoderConfig({ type: 'js' });
export const dracoLoader = draco;

// gltf
const gltf = new GLTFLoader();
gltf.setDRACOLoader( dracoLoader );
export const gltfLoader = gltf;

BONUS for those who like promises, I've also been making my loaders return promises with the following:

function promisify(loader, onProgress) {
  function promiseLoader(url) {
    return new Promise((resolve, reject) => {
      loader.load(url, resolve, onProgress, reject);
    });
  }
  return {
    originalLoader: loader,
    load: promiseLoader,
  };
}

Example usage:

import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader';

export const fbxLoader = promisify(new FBXLoader());

Then elsewhere:

import { fbxLoader } from './loaders'

fbxLoader.load('cat.fbx').then(model => {
  console.log(model)
})

Upvotes: 1

Ben E G
Ben E G

Reputation: 971

I like the answer from @marrion luaka (and upvoted it) but referencing locally.

Only changed:

dracoLoader.setDecoderPath('https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/js/libs/draco/'); // use a full url path

To this:

dracoLoader.setDecoderPath( '../node_modules/three/examples/js/libs/draco/gltf/' );

Upvotes: 5

Vikram Hegde
Vikram Hegde

Reputation: 650

Host the draco folder in cloud then

import DRACOLoader from './DRACOLoader';
DRACOLoader.setDecoderPath(path to hosted draco folder);

worked for me.

if you do like this,

DRACOLoader.setDecoderPath('./draco/')

then react will take it as,

DRACOLoader.setDecoderPath('localhost:3000/draco/');

so it wont work.

Upvotes: 3

Related Questions