GLTF2 GLB exporter is producing invalid glb file

Hello all,
I am using an express app and a page has a 3d asset viewer. I am trying to add a download glb functionality by using this documentation - glTF Exporter | Babylon.js Documentation .

The cdn provided specifically for the gltf exporter is not working and hence i used the serializer one.

Everything seems to working fine as the “glb file” is downloaded but when i try to upload the same file in babylonjs sandbox, it suggests that the file is not valid.
Can anyone lead me to a detailed documentation for the gltf exporter ?
or maybe a playground where gltf exporter is working.

You can open Sandbox or Playground, then open Inspector and export your scene as .babylon or .glb file.

1 Like

thankyou for such a quick reply. The thing is i am trying to add a similar functionality in my project.
“A button to download the current 3d file in glb format”.
The download is working fine but there are times when the downloaded file is “empty” or “invalid”.
Also every file has a “root” inside the “root” which is not desirable by me.
Is there a detailed documentation for “gltf2 exporter” ?

Here is the source code for GLTF serializer

2 Likes

What do you mean by this:

The cdn provided specifically for the gltf exporter is not working and hence i used the serializer one.

The glTF export should work: would you have a repro in the Playground which produces an invalid glb file?

1 Like

Thankyou so much @labris , I am now able to donwload the glb files by using “shouldExportNode”.
I had to avoid loading everything else in my scene (like lights, planes, camera etc) to make the downloaded glb valid.
here’s what it looks like.

shouldExportNode: function (node) {
return ((node !== camera) && (node !== spotLight) && (node !== hemiLight) && (node !== dirLight) && (node !== shadowPlane) && (node !== parentBox))
}

1 Like

Thankyou @Evgeni_Popov , but the issue has been resolved for the time being.

My next challenge is sending this glb file to the server instead of donwloading it straightaway.

Is there a way of sending glb files using “file type” inputs in an html form ?

I mean, creating an html form and adding the glb file to an input tag and then sending a post request which will bear the file alongwith.

let me add @RaananW for this, but why not using a xmlhttprequest or post instead of multipart form ?

yes, you can create a File object that can be used in a . In general:

  1. Read the binary data (you probably have an arraybuffer?)
  2. convert the array buffer to a blob (new Blob([buffer])
  3. Use the blob to create a File object: new File([blob]))
  4. Use the File object in your form

But just as @sebavan said - the simpler way would be to simply send a POST (or PUT) request to an endpoint accepting binary data. Or convert the data to base64 and send it as a string (and convert it back server-side). All viable options, depending on your architecture.

3 Likes

Thankyou @RaananW , I am fairly new to web development and babylonjs but i’ll surely explore the steps that you have suggested above.

1 Like

Sure! Let me know if it works :slight_smile:

1 Like

hello @RaananW , I am here again to disturb you :sweat_smile: :laughing:.

Now i am using the sceneSerializer as i want to save the complete scene and write that in a folder as a “.babylon” file. Everything works fine as the .babylon file is created in the right folder but when i try to import the “exported” scene in sandbox, it gives an error.

sandbox error - Unable to load from file:black_shoes.babylon: loadAssets of unknown Lights: Name: hemiLight, type: Hemispheric Name: spotLight, type: Spot Name: dirLight, type: Directional Materials: Name: groundMat

here is the code -

let serializedScene = await BABYLON.SceneSerializer.SerializeAsync(scene);
        let strScene = JSON.stringify(serializedScene);
        let objectUrl;
        console.log(strScene);
        if (objectUrl) {
            window.URL.revokeObjectURL(objectUrl);
        }
        const blob = new Blob([strScene], { type: "octet/stream" });
        // sending blob as form data
        document.getElementById("sceneBlob").value = JSON.stringify(blob);

on the server side -

// parsing stringified blob
const sceneBlob = JSON.parse(req.body.sceneBlob)

    fs.writeFile(process.cwd() + "./myFilePath", sceneBlob, (error) => {
        if (error) {
            console.error('an error occurred : ', error);
        } else {
            console.log('file created!');
        }
    })

generated .babylon file - Dropbox - black_shoes.babylon - Simplify your life

Please help me out :pray:!!

hmmmm

This seems to be on us. But I wonder what has changed?

The issue is that one of the textures is set as base64, but we are adding the protocol file: when loading this.

I want to see first if we have changed something or is it a long-standing bug that we are just now detecting.

1 Like

Make sure not to add rootUrl to data URLs when parsing textures by RaananW · Pull Request #13847 · BabylonJS/Babylon.js (github.com)

2 Likes

So, @RaananW
should i change something in my code or should i wait for the babylon team to make changes.
:sweat_smile: :sweat_smile:

If I need to change something then please suggest the required code changes.

Thanks in advance!!

no need to change. it is a use case we simply didn’t cover yet. it will be available tomorrow in the playground, and probably next week in an npm release

1 Like

ok thank you so much.
This is another thing i love about babylonjs. “The Support” !! :muscle::grin:

3 Likes

hello @RaananW, @sebavan, @labris
There is an update in the situation

Now, i am “downloading” and “writing” the scene.babylon file at the same time to compare the two.

code for downloading scene file -

        let serializedScene = await BABYLON.SceneSerializer.SerializeAsync(scene);
        let strScene = JSON.stringify(serializedScene);
        let objectUrl;
        console.log(strScene);
        if (objectUrl) {
            window.URL.revokeObjectURL(objectUrl);
        }
        // const blob = new Blob([strScene], { type: "octet/stream" });
        const blob = new Blob([strScene], { type: "application/json" });

        // downloading .babylon file
        let exportedFilename = document.getElementById("projectName").innerText + ".babylon"
        objectUrl = (window.webkitURL || window.URL).createObjectURL(blob);
        var link = window.document.createElement('a');
        link.href = objectUrl;
        link.download = exportedFilename;
        var click = document.createEvent("MouseEvents");
        click.initEvent("click", true, false);
        link.dispatchEvent(click);

The file being downloaded - Dropbox - scene.babylon - Simplify your life
It is working in the sandbox but the shadows are not exported along with the scene.

code for writing scene file -

        // javasript code
        let serializedScene = await BABYLON.SceneSerializer.SerializeAsync(scene);
        let strScene = JSON.stringify(serializedScene);
        let objectUrl;
        console.log(strScene);
        if (objectUrl) {
            window.URL.revokeObjectURL(objectUrl);
        }
        const blob = new Blob([strScene], { type: "application/json" });

        // sending blob as form data to write .babylon file
        document.getElementById("glbBlob").value = JSON.stringify(blob);

        // server side
        const glbBlob = req.body.glbBlob
        // writing file
        fs.writeFile(process.cwd() + "./myfilepath", glbBlob, (error) => {
          if (error) {
              console.error('an error occurred : ', error);
          }   else {
              console.log('file created!');
          }
        })

The scene.babylon file that i’m writing in the folder is not a valid file because the size is too small compared to the file being downloaded.

Now, Am i doing something wrong while writing the file because the downloaded file is working but when i try to write the same file it is an invalid file.

Please help !! :pray: :pray: :sweat_smile: