Implementing sceneLoader in react babylon

Hi, I am trying to implement something like this: https://playground.babylonjs.com/#7F6S08#2
The above code renders 3D model after converting into binary stream.
I am trying to do the same in react babylon using and . However, I am receiving the following error: webRequest.ts:119 Not allowed to load local resource: blob:null/a7cf7204-89cd-4c37-8933-487cac9deb4e

Below is my code:
renderModel = (rootURL) => {
console.log(“renderModel”);
this.setState({
…this.state,
url: rootURL,
id: “after”
})
}

runXHR = (loadModel) => {
    var url = "/modelURL"
    var binaryString = "";
    
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, true);
    xhr.responseType = "blob";
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            if (((xhr.status === 200) || (xhr.status == 0)) && (xhr.response)) {
                var reader = new FileReader();
                reader.onloadend = function () {
                    binaryString = reader.result;
                    binaryString = binaryString.replace("application/octet-stream;", "");
                    loadModel(binaryString);
                }
                reader.readAsDataURL(xhr.response);
            }
        }
    }

    xhr.send(null);
}

loadModel = (base64_model_content) => {
	
	var raw_content = this._base64ToArrayBuffer(base64_model_content.replace("data:base64,", ""));
    var blob = new Blob([raw_content]);
    var url = URL.createObjectURL(blob);
    url=url.replace("http://localhost:3000","null");
    console.log(url);
    
    this.renderModel(url);        
}

_base64ToArrayBuffer(base64) {
    var binary_string = window.atob(base64);
    var len = binary_string.length;
    var bytes = new Uint8Array(len);
    for (var i = 0; i < len; i++) {
        bytes[i] = binary_string.charCodeAt(i);
    }
    return bytes.buffer;
}

render() {
    return (
            <div className="mainScene">
                <button onClick={() => this.runXHR(this.loadModel)}>Click</button>
                <Engine antialias adaptToDeviceRatio canvasId="sample-canvas">
                    <Scene canvasId="scene_1">                            
                        <ArcRotateCamera name="arc" target={new Vector3(0, 1, 0)} minZ={0.001}
                            alpha={-Math.PI / 2} beta={(0.5 + (Math.PI / 4))} radius={5} lowerRadiusLimit={5} upperRadiusLimit={10} />
                        <HemisphericLight name='hemi' direction={new Vector3(0, -1, 0)} intensity={0.8} />
                        <Model
                            rotation={new Vector3(0, -15, 0)} key={this.state.id} position={new Vector3(0, 0, 0)}
                            rootUrl={this.state.url} sceneFilename=""
                            scaling={new Vector3(1, 1, 1)} />
                        <EnvironmentHelper options={{ enableGroundShadow: true, groundYBias: 1 }} mainColor={Color3.FromHexString("#74b9ff")} />
                    </Scene>
                </Engine>
            </div>           
    )
}

}

Why that? You should just use the url returned by createObjectUrl

Since my app is running on localhost:3000. Removing url.replace(“http://localhost:3000”,“null”); also doesn’t help

object url is not a real url, you should not replace it at all but instead leave it unchanged

Without a repro it is complicated to help you

I didn’t get your point. What all changes do I need to do?

A blob URL is not an http URL, it has a different schema and is not relative to your server in any way.
Also, replacing ANYTHING in a string with the string “null” will probably not be what you meant to do. Which probably correlates to the error you provided at the beginning of your message.

I believe this is the most important piece of information you need right now :slight_smile:
We can’t really help without seeing what the problem is.

Thanks for the information. I have a further doubt. I have a code that generates binary stream of my fetched glb model and then displays it using blob url. It works fine in babylon.js. However, providing the same blob url with react babylon shows me this error: webRequest.ts:119 Not allowed to load local resource: blob:null/a7cf7204-89cd-4c37-8933-487cac9deb4e
What is the work-around for it?

I have no idea why you have null in your blob url. But this might be the issue. And again, it’s very hard to help with this issue without some form of demo.

Hi, here is the link to my code:

The index.html file contains babylon.js code which works fine for me. I am trying to convert it to react babylon and facing issues in it, the code for which is in MainScene.js.

@brianzinn could you please suggest me the solution for it?

I would suggest it’s in your loadModel - it doesn’t look right. Probably that could be put on a playground. I have back to back meetings for next 4 hours, but will give it a go tonight. Also, buffer does Base64 convesion, but you don’t need to convert to base64 and also your uintarray looks to be wrong length - it should be new Uint8Array(new ArrayBuffer(len));. If you make a playground people can help you - Cheers.

The current code is able to generate an object url for me. But I am not able to display my model in using that URL.

Yes, I was re-reading through your code and comments. Looks like you want to set the URL to a model. Could it be that you are just missing the pluginExtension as “.glft”, as you have in your other project?

Yes, I guess that is the issue. I have no idea about how to mention the object type as gltf in react babylon as I did in my babylon code

I’m trying to set it up to run locally to see for myself, but to add that:

<model rootUrl=... pluginExtension=".gltf" />

I can confirm that adding the pluginExtension worked for me :slight_smile: The .gltf that I used had a bunch of other assets and textures that didn’t load - it’s because there is no rootUrl to download the additional assets from. Check your network log - mine looked like this (but it means the GLTF parsed ok):

Hi, thanks a lot @brianzinn . pluginExtension works fine for me. Thanks a lot for your time and efforts!

1 Like