Getting error not found when using base64 draco_decoder.wasm

I want to create playable ads and integrate Draco libraries directly into the final bundle.js. , I’ve converted draco_decoder.wasm and draco_wasm_wrapper.js into base64 strings, but I’m encountering the following error:

draco_wasm_wrapper.js net::ERR_ABORTED 404 (Not Found)

The application is trying to access it at: https://localhost:8080/draco_wasm_wrapper.js. Can anyone help me resolve this issue?


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

// Base64 strings for the Draco files
const base64Wasm = '...'; // base64 string for draco_decoder.wasm
const base64Js = '...';   // base64 string for draco_wasm_wrapper.js

// Function to convert Base64 to Uint8Array for WASM
function base64ToUint8Array(base64) {
    const binaryString = atob(base64);
    const len = binaryString.length;
    const bytes = new Uint8Array(len);
    for (let i = 0; i < len; i++) {
        bytes[i] = binaryString.charCodeAt(i);
    }
    return bytes;
}

// Function to create a Blob URL from Base64 for JS
function base64ToBlobUrl(base64) {
    const binaryString = atob(base64);
    const len = binaryString.length;
    const bytes = new Uint8Array(len);
    for (let i = 0; i < len; i++) {
        bytes[i] = binaryString.charCodeAt(i);
    }
    const blob = new Blob([bytes], { type: 'application/javascript' });
    return URL.createObjectURL(blob);
}

// Convert base64 strings
const wasmBinary = base64ToUint8Array(base64Wasm);
const jsBlobUrl = base64ToBlobUrl(base64Js);

// Set up DRACOLoader
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderConfig({
    wasmBinary: wasmBinary,
    jsPath: '',              // Leave empty
    jsSource: jsBlobUrl,    // Use the Blob URL
});

// Set up GLTFLoader
const gltfLoader = new GLTFLoader();
gltfLoader.setDRACOLoader(dracoLoader);

// Load a GLTF model
const modelUrl = 'model.gltf';
gltfLoader.load(
    modelUrl,
    (gltf) => {
        scene.add(gltf.scene);
    },
    (xhr) => {
        console.log((xhr.loaded / xhr.total * 100) + '% loaded');
    },
    (error) => {
        console.error('An error occurred while loading the GLTF model', error);
    }
);

DarcoLoader extends the Loader class. When dealing with URL.createObjectURL(blob), you need to use a LoadingManager. With manager.setURLModifier, you can intercept any URL that should point to a blob URL and replace it with the actual blob URL generated by URL.createObjectURL(blob).

It should look like the following:

const manager = new THREE.LoadingManager();

// Intercept requests for Draco files and replace with Blob URLs
manager.setURLModifier((url) => {
    if (url.includes('draco_decoder.wasm')) 
        return wasmBlobURL;

    if (url.includes('draco_wasm_wrapper.js')) 
        return jsBlobUrl;

    return url;
});

// Set up DRACOLoader with the custom manager
const dracoLoader = new DRACOLoader(manager);
dracoLoader.setDecoderPath('draco/'); // Use a virtual path, intercepted by LoadingManager

As an alternative, use a CDN to load the Darco files. Instead of storing the base64 data, you can try the following approach :crossed_fingers: (though I’m not entirely sure about this, a feedback would be appreciated)

const CDNPath = 'https://unpkg.com/browse/three@0.169.0/examples/jsm/libs/draco/';
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath(CDNPath);
1 Like

Thank you, @Fennec. Your first code is exactly what I wanted. :cowboy_hat_face:
However, for the second point, playable ads should not make any HTTP requests.

1 Like

hello, now I have same problem. But when I converc draco to base64 it takes almost 700kb. thats too much for my project. Do u fix it somehow?

Here is the minified version
base64JS.ts (76.1 KB)
base64Wasm.ts (250.6 KB)

1 Like