Loading asset data from local files in nodejs

:white_check_mark:Update: full solution: Loading asset data from local files in nodejs - #4 by NightSkies

Hi,

We’re using babylon engine on the serverside for some things. I’m having some issues loading glb files.
It errors out with this:

envFileDataURL blob:nodedata:a3f3a68d-5d54-4838-8679-45
BJS - [22:53:15]: Unable to find a plugin to load gltf files. Trying to use .babylon default plugin. To load from a specific filetype (eg. gltf) see: https://doc.babylonjs.com/features/featuresDeepDive/importers/loadingFileTypes
(node:10468) [DEP0170] DeprecationWarning: The URL blob:nodedata:a3f3a68d-5d54-4838-8679-452f7e22c092 is invalid. Future versions of Node.js will throw an error.
This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason:
Error
    at XMLHttpRequest.send ( ... \node_modules\xhr2\lib\xhr2.js:281:19)
    at e.send (webpack://BABYLON/../../../dev/core/src/Misc/webRequest.ts:178:19)
    at retryLoop (webpack://BABYLON/../../../dev/core/src/Misc/fileTools.ts:678:21)
    at requestFile (webpack://BABYLON/../../../dev/core/src/Misc/fileTools.ts:681:9)
    at RequestFile (webpack://BABYLON/../../../dev/core/src/Misc/fileTools.ts:724:9)
    at C (webpack://BABYLON/../../../dev/core/src/Misc/fileTools.ts:496:12)
    at t._loadFile (webpack://BABYLON/../../../dev/core/src/scene.ts:5416:25)
    at manifestChecked (webpack://BABYLON/../../../dev/core/src/Loading/sceneLoader.ts:737:25)
    at Function._LoadData (webpack://BABYLON/../../../dev/core/src/Loading/sceneLoader.ts:759:13)
    at Function._LoadAssetContainer (webpack://BABYLON/../../../dev/core/src/Loading/sceneLoader.ts:1531:28)
    at webpack://BABYLON/../../../dev/core/src/Loading/sceneLoader.ts:1639:25
    at new Promise (<anonymous>)
    at Function.e.LoadAssetContainerAsync (webpack://BABYLON/../../../dev/core/src/Loading/sceneLoader.ts:1638:16)
...

Relevant code:

  const environmentModel = await readFile(
    "<local filesystem path to glb here, its reading successfully",
  ); 
  const envFileBlob = new Blob([environmentModel]);
  // const envFile = new File([environmentModel], "baseModel.glb");

  const envFileDataURL = URL.createObjectURL(envFileBlob);

  console.log('envFileDataURL', envFileDataURL.slice(0, 40));

  const container = await BABYLON.SceneLoader.LoadAssetContainerAsync(
    envFileDataURL,
    scene,
    { pluginExtension: "gltf" },
  );

Perhaps I’m not properly forming the data URL (maybe must begin with data: …).
The relevant resources on this don’t seem focused on nodejs. Anyone have experience with this?
I tried this but it errors out with “FileReader not found” (is that referring to an HTML5 API?): Importing gltf ArrayBuffers from loaders.gl - #2 by br-matt

Thanks


:white_check_mark:Update: full solution: Loading asset data from local files in nodejs - #4 by NightSkies

If you use ES6 imports, don’t forget to import

import "@babylonjs/loaders/glTF"

1 Like

I believe you used the wrong parameters for the container.
Example - https://playground.babylonjs.com/#FIWM5X#49
For your case it should be

  const container = await BABYLON.SceneLoader.LoadAssetContainerAsync(
    envFileDataURL, // rootUrl or full URL
    undefined, // since we have full URL this parameter is undefined
    scene, // the scene is the 3rd parameter
    undefined, // onProgress callback
    ".gltf") // File extension
  );

I noticed my file already imports some kind of loaders package. Trying to import only the loader I wanted didn’t seem to work. After I moved on from that I found extension and the dataurl were the only issues.

Adding extension like above did help! Documentation does not make this clear.
https://doc.babylonjs.com/typedoc/classes/BABYLON.SceneLoader#LoadAssetContainerAsync
Perhaps samples do

Also I had to form the dataurl by hand to get it to load. Node’s createDataURL doesnt seem to work properly here?

import * as BABYLON from "babylonjs";
import "babylonjs-loaders";
import { readFile } from "fs/promises";

// ...

const environmentModel = await readFile(
    "./thelocalfilepath.glb",
  );
  const envFileb64 = Buffer.from(environmentModel).toString("base64");
  const envFileDataURL = "data:model/gltf-binary;base64," + envFileb64;

  console.log("envFileDataURL", envFileDataURL.toString().slice(0, 40));

  const container = await BABYLON.SceneLoader.LoadAssetContainerAsync(
    envFileDataURL,
    undefined,
    scene,
    undefined,
    ".gltf",
  );

1 Like

This is part of this doc Babylon.js docs

1 Like

Ah I missed that one! I tend to look at API docs more than tutorials.