Running on server throws no-plugin error

Hi~!

I have been trying to use Babylon on the server-side with TypeScript + Node.js

I have successfully rendered using node-based canvas with .babylon 3D model.

However, when trying to load .gltf 3D model, it keeps saying Unable to find a plugin to load undefined files.

const BBJS = require('babylonjs')
import "@babylonjs/loaders";
import "@babylonjs/core";
// import { SceneLoader } from '@babylonjs/core';
// above commented import will be used later in an example. //


export class ModelSceneBuilder {
  protected canvas: any;
  protected engine: any;
  protected scene: any;
  protected camera: any;

  constructor(canvas:any) {
    this.canvas = canvas;
  }

  async init() {
    this.engine = new BBJS.Engine(this.canvas, true, { preserveDrawingBuffer: true, stencil: true })
    this.scene = new BBJS.Scene(this.engine)
    this.camera = new BBJS.FreeCamera('cam1', new BBJS.Vector3(10, 15, -20), this.scene)
    this.camera.setTarget(BBJS.Vector3.Zero())
    this.camera.attachControl(this.canvas, false)
    const sphere = BBJS.Mesh.CreateSphere('sphere1', 16, 2, this.scene, false, BBJS.Mesh.FRONTSIDE);

    this.engine.runRenderLoop(() => {
      this.scene.render()
    })
  }

  async loadModel(rootURL:string, fileName:string) {
    const isPlugInAvailable = BBJS.SceneLoader.IsPluginForExtensionAvailable(".gltf")
    console.log(`Plugin Availability For GLTF ==== ${isPlugInAvailable} ====`);

    BBJS.SceneLoader.ImportMesh('', rootURL, fileName, this.scene, null)

  }

}

With import "@babylonjs/loaders"; or even import "@babylonjs/loaders/GLTF"; , I still get this error message

Babylon.js v4.2.0 - WebGL1
Plugin Availability For GLTF ====> false
BJS - [09:38:48]: Unable to find a plugin to load .gltf files. Trying to use .babylon default plugin.

For some reason, when I use a separate import for the SceneLoader like this

import { SceneLoader } from '@babylonjs/core';
...
...
async loadModel(rootURL:string, fileName:string) {
  const isPlugInAvailable = SceneLoader.IsPluginForExtensionAvailable(".gltf")
  console.log('Plugin Availability For GLTF ====>', isPlugInAvailable);

  SceneLoader.ImportMesh('', rootURL, fileName, this.scene, null)

}

I finally get true for gltf plugin availability check, throws some other error message

Babylon.js v4.2.0 - WebGL1
Plugin Availability For GLTF ====> true
-=-on server error-=- ReferenceError: indexedDB is not defined
    at new Database (webpack-internal:///./node_modules/@babylonjs/core/Offline/database.js:40:41)
    at Function._Engines_engine__WEBPACK_IMPORTED_MODULE_3__.Engine.OfflineProviderFactory (webpack-internal:///./node_modules/@babylonjs/core/Offline/database.js:23:12)
    at Function.SceneLoader._LoadData (webpack-internal:///./node_modules/@babylonjs/core/Loading/sceneLoader.js:218:93)
    at Function.SceneLoader.ImportMesh (webpack-internal:///./node_modules/@babylonjs/core/Loading/sceneLoader.js:370:28)

Could all these be an issue caused by the way next.js, npm, typescript, etc. are set up in my project?

I guess this error is related to babylon.js implementation. SceneLoader.ImportMesh is trying to cache the loaded model blob data to browser’s indexdb, which doesn’t exist in your node runtime.

-=-on server error-=- ReferenceError: indexedDB is not defined

I have not worked with server-side babylon much. But 2 possibilities you can try:

  1. Can you try to pass base64 content of your model instead of loading it from a URL? I haven’t checked the code. But hopefully it bypasses accessing indexDB.
  2. Try to use a fake indexDB? E.g. Found by google, I personally never used it before: fake-indexeddb - npm

Otherwise wait for experts to reply. :smile:

Update: It seems offline support is default on and can be turned off in babylon.js: Optimizing Using Cached Resources | Babylon.js Documentation

You are mixing UMD and es6 packages, which won’t work as you would want it to. You should remove the reference to the project “babylonjs” and use “@babylonjs/core” instead.

@RaananW oh~~!! Thanks! You were right! The conflict was the cause :frowning:
Though, I still get this error message.

error - node_modules/@babylonjs/core/Misc/fileTools.js (148:17) @ Function.FileTools.LoadImage
TypeError: URL.createObjectURL is not a function

Should I try to pass base64 of the model instead of an URL like @slin suggested?

@slin , by the way, I am not too sure what you meant by passing base64 of the model.

Where should I pass it to? When using SceneLoader.ImportMesh('', rootURL, fileName)?

I didn’t know a 3D model can be converted into base64! :open_mouth:

My reply was for the last error you had about indexDB. And my suggestion was to turn off the offline support: Optimizing Using Cached Resources | Babylon.js Documentation

Babylon.js v4.2.0 - WebGL1
Plugin Availability For GLTF ====> true
-=-on server error-=- ReferenceError: indexedDB is not defined

For the new error you have:

TypeError: URL.createObjectURL is not a function

What is your node.js version? URL.createObjectURL is supported since node.js v16.7.0: URL | Node.js v21.2.0 Documentation

I apologize for the confusion. I followed the path logged in terminal which is node_modules/@babylonjs/core/Misc/fileTools.js

Then I saw the input type of base64 here, but it was not for loading meshes, but for an image. My bad.

I wonder where the error came from though hmm

@DOEHOONLEE

I updated my answer above. Please check if it helps.

The problem with indexDB was solved with the help of you and @RaananW . Thank you :slight_smile:

It throws another error though

error - node_modules/@babylonjs/core/Misc/fileTools.js (148:17) @ Function.FileTools.LoadImage
TypeError: URL.createObjectURL is not a function

The code works perfectly fine with .babylon file, but not with .gltf files…

I matched the versions of @babylon/core and @babylon/loaders to 4.2.0

Let me paste my reply here:

TypeError: URL.createObjectURL is not a function

What is your node.js version? URL.createObjectURL is only supported since node.js v16.7.0: URL | Node.js v18.7.0 Documentation

1 Like

oops I did not see that part. I didn’t know it was updated. I’m sorry.

Oh dang it’s supported from Node version after 16?

I’m on 12.- right now… hmm… I think highering my node version would cause conflicts with other settings, but let me just try if I can get passed through this URL.createObjectURL error.

Thanks again :slight_smile:

1 Like

I solved my original problem (indexDB thingy) by using importing from @babylon/core and removing babylonjs package.

and that is when I got this problem below

error - node_modules/@babylonjs/core/Misc/fileTools.js (148:17) @ Function.FileTools.LoadImage
TypeError: URL.createObjectURL is not a function

So I started my porject with higher node version (16.7.0) like you recommended, but then I am back to this error again… :frowning:

Babylon.js v4.2.0 - WebGL1
Plugin Availability For GLTF ====> true
-=-on server error-=- ReferenceError: indexedDB is not defined
    at new Database (webpack-internal:///./node_modules/@babylonjs/core/Offline/database.js:40:41)
    at Function._Engines_engine__WEBPACK_IMPORTED_MODULE_3__.Engine.OfflineProviderFactory (webpack-internal:///./node_modules/@babylonjs/core/Offline/database.js:23:12)

Hmm… ah… every problem that I encounter seems to be some project setup I guess

1 Like

@RaananW I guess the error is from this line: https://github.com/BabylonJS/Babylon.js/blob/master/packages/dev/core/src/Offline/database.ts#L29

When running in node runtime, window is undefined. Therefore this line evaluates to

private _idbFactory = indexedDB

And indexedDB is also not defined in node runtime. Thus @DOEHOONLEE is getting the error.

1 Like

How could I pass fake-indexeddb for Babylon to use? Wouldn’t fake-indexddb or mock-browser solve the problem?

You don’t pass fake-indexeddb to babylon.js. I have not used it. But I guess you need to import indexdedDB

import {
    indexedDB as fakeIndexedDB,
} from "fake-indexeddb";

And then add indexedDB to global object of node runtime.

2 Likes

That’s one way of solving it, yes :blush:

On our end, i can make sure database only initializes if everything required (i.e. URL and indexedDB) is available. This will make the database not be available in certain systems, but that’s acceptable as it is anyhow the case on those systems

3 Likes

About this solution of yours,

Blockquote
Let me paste my reply here:

TypeError: URL.createObjectURL is not a function

What is your node.js version? URL.createObjectURL is only supported since node.js v16.7.0: URL | Node.js v18.7.0 Documentation

is this the case for front-end side as well?

Because I do have another project running Babylon.js on the front-end side only with node version at 12.- and it works fine.

URL is a member of the window object in the browser. Your node version has nothing to do with the browser babylon is running on. When running on the server then the running environment is no longer a browser. It is node, and therefore you need to make sure that the environment has everything you need.
Other environments like Deno or Bun (and future versions of node) do have the needed API, so if you run it on the server you will need to use one of those to make sure it is working as expected.

1 Like
1 Like