Running on server throws no-plugin error

For this part, did you mean that there is something needs to be fixed in my project?

No. I would suggest you to create a minimum babylon.js project that you can reproduce the errors, excluding the next.js, http server, etc. Maybe start with a single .ts file that can be used to reproduce the error from URL.createObjectURL(). And ask if babylon team can help investigating.

The “obj” argument must be an instance of Blob. Received an instance of Blob
at new NodeError (node:internal/errors:372:5)
1 Like

Ohh, alright. Let me try to reproduce in just node.hs based project.

Wait. I’m sorry I’m a little confused. I do agree with excluding Next.js part, but why http server?

I thought the whole point was to find what is wrong when running Babylon on the server side? :frowning:

Since the suspect is the error is caused by URL.createObjectURL in node.js runtime. The http server is out of the scope for reproducing this error. So the bare minimum would be just babylon NullEngine and gltf loader to import your model running in node.js.

1 Like

Oh, I get it. Alright!

Yes, there were changes. None of them should cause any real issues though. I’m not sure I’m following the thread. Is there a repro for the base64 issue?

1 Like

There is this project on Github I am trying to use. The project has the very basic setup and it renders a sphere on server side → [link].

What I did was

  • git clone https://github.com/akira-cn/node-canvas-webgl.git

  • modify file test/babylon.js like this below

const fs = require('fs');
const BABYLON = require('babylonjs');
const {createCanvas} = require('../lib');

// polyfill
global.HTMLElement = function () {};
global.window = {
  setTimeout,
  addEventListener() {},
};
global.navigator = {};
global.document = {
  createElement() {
    return createCanvas(300, 150);
  },
  addEventListener() {},
};

// Get the canvas DOM element
const canvas = createCanvas(512, 512);

// Load the 3D engine
const engine = new BABYLON.Engine(canvas, true, {preserveDrawingBuffer: true, stencil: true});

// CreateScene function that creates and return the scene
const createScene = function () {
  // Create a basic BJS Scene object
  const scene = new BABYLON.Scene(engine);
  // Create a FreeCamera, and set its position to {x: 0, y: 5, z: -10}
  const camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 5, -10), scene);
  // Target the camera to scene origin
  camera.setTarget(BABYLON.Vector3.Zero());
  // Attach the camera to the canvas
  camera.attachControl(canvas, false);
  // Create a basic light, aiming 0, 1, 0 - meaning, to the sky
  const light = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 1, 0), scene);
  // Create a built-in "sphere" shape; its constructor takes 6 params: name, segment, diameter, scene, updatable, sideOrientation
  const sphere = BABYLON.Mesh.CreateSphere('sphere1', 16, 2, scene, false, BABYLON.Mesh.FRONTSIDE);
  // Move the sphere upward 1/2 of its height
  sphere.position.y = 1;
  // Create a built-in "ground" shape; its constructor takes 6 params : name, width, height, subdivision, scene, updatable
  const ground = BABYLON.Mesh.CreateGround('ground1', 6, 6, 2, scene, false);
  
  const isPluginAvailable = BABYLON.SceneLoader.IsPluginForExtensionAvailable('.babylon')
  
  console.log('Plugin Availability ::::: ', isPluginAvailable)
  
  BABYLON.SceneLoader.ImportMesh('', 'https://playground.babylonjs.com/scenes/', 'dummy2.babylon', scene, null)
  
  // Return the created scene
  return scene;
};

// call the createScene function
const scene = createScene();

scene.render();

fs.writeFileSync('./snapshot/snap-babylon.png', canvas.toBuffer());
// run the render loop
// engine.runRenderLoop(() => {
//   scene.render();
// });

  • run node test/babylon.js

Then it produces infinite log on the terminal like this

var n=function(e,t){return(n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i])})(e,t)};function r(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function i(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(i.prototype=t.prototype,new i)}var o=function(){return(o=Object.assign||function(e){for(var t,i=1,n=arguments.length;i<n;i++)for(var r in t=arguments[i])Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e}).apply(this,arguments)};function a(e,t,i,n){var r,o=arguments.length,a=o<3?t:null===n?n=Object.getOwnPropertyDescriptor(t,i):n;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,i,n);else for(var s=e.length-1;s>=0;s--)(r=e[s])&&(a=(o<3?r(a):o>3?r(t,i,a):r(t,i))||a);return o>3&&a&&Object.defineProperty(t,i,a),a}function s(e,t,i,n){return new(i||(i=Promise))((function(r,o){function a(e){try{c(n.next(e))}catch(e){o(e)}}function s(e){try{c(n.throw(e))}catch(e){o(e)}}function c(e){var t;e.done?r(e.value):(t=e.value,t instanceof i?t:new i((function(e){e(t)}))).then(a,s)}c((n=n.apply(e,t||[])).next())}))}function c(e,t){var i,n,r,o,a={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]};return o={next:s(0),th....

@bghgary, I have succeeded in rendering on server side using BabylonJS and even with ThreeJS, but had a problem when trying to load models :frowning:

@slin , I also tried loading a model the way you did with base64

const rawContent = fs.readFileSync('/Users/david/Documents/dummy2.babylon')
const base64Content = Buffer.from(rawContent).toString('base64')
const base64ModelString = `data:base64,${base64Content}`
const { meshes, skeletons } = await BABYLON.SceneLoader.ImportMesh('', '', base64ModelString, scene)

and still got this error

BJS - [17:00:24]: Unable to import meshes from data:base64,ewogICJwcm9kdWNl

Hmm… I think this is the smallest unit project I can reproduce

@RaananW any ideas ?

Yes, node is missing XHRHttpRequest, so it fails

Do this:

const XMLHttpRequest = require("xhr2");
global.XMLHttpRequest = XMLHttpRequest;

of course after installing xhr2 using npm.

The snapshot will not work they way you do it, because you are not waiting for the model to be loaded. However, it is loaded correctly now without any issues.

OMG. I’m sorry I forgot to include it.

I’m not sure if you remember what happend to loading .babylon model early in the discussion.

Yes, .babylon model can be loaded, but the texture mapping is quite off. I have no idea :frowning:
and .gltf cannot be loaded…

const fs = require('fs');
const BABYLON = require('babylonjs');
const { createCanvas } = require('../lib');
const XMLHttpRequest = require("xhr2");

global.XMLHttpRequest = XMLHttpRequest;

global.HTMLElement = function () {};
global.window = {
  setTimeout,
  addEventListener() {},
};
global.navigator = {};
global.document = {
  createElement() {
    return createCanvas(300, 150);
  },
  addEventListener() {},
};

const canvas = createCanvas(512, 512);

const engine = new BABYLON.Engine(canvas, true, {preserveDrawingBuffer: true, stencil: true});
const scene = new BABYLON.Scene(engine);

const createScene = async function () {
  scene.clearColor = new BABYLON.Color4(0.5, 0.4, 0.4, 1);
  const camera = new BABYLON.FreeCamera('cam1', new BABYLON.Vector3(-6.8, 9.8, -9.3), scene)
  camera.setTarget(new BABYLON.Vector3(-1.8, 0, 0))
  const rootURL = 'https://playground.babylonjs.com/scenes/'
  const fileName = 'candle.babylon'
  
  const { meshes } = await BABYLON.SceneLoader.ImportMeshAsync('', rootURL, fileName, scene, null, '.babylon')
  
  const light = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 1, 0), scene);
  
  scene.render();
};

createScene();


setTimeout(() => {
  fs.writeFileSync('./snapshot/snap-babylon.png', canvas.toBuffer());
}, 3000)

with this, I can load .babylon models like these



but only the ones without textures.

Earlier in this discussion, I asked and mentioned the problem where .babylon model can be loaded, but textures were kinda off.

Now with babylonjs 5.22.1 version, I cannot load with above code at all :frowning:

What node version are you running? 5.22 introduced es2021, which is supported by node 16, but will probably need transpilation with older versions of node

@bghgary - was anything changed in the way we load base64-based models in the gtlf loader?
(please be patient, he is away until the beginning of next week).
I will anyhow try finding time to debug this, but not sure when it’ll happen. sorry…

Ah, I forgot this message after I came back from a long weekend lol…

I am using node -v 16.16.0

I’ll share a repo in a few hours to be clear :slight_smile:

1 Like

Here’s the link to the repo! DOEHOONLEE/babylonNodeJS (github.com)

Even though the texture mapping was off, I could load a .babylon model before, but not anymore. I felt so close to making it work :frowning:

My ultimate goal would be to make it work with .gltf model though.

What exactly happens? Your code seems to be working as you expect it to work:

  1. The example pictures I shared are all from models without texture references.

So for example, if you replace the rootURL and the fileName with https://playground.babylonjs.com/scenes/Dude/Dude.babylon which has textures
Screen Shot 2022-09-13 at 10.59.03 PM

it wouldn’t work.

In @slin 's example as well, it seems to be working, but it also uses a model without texture mapping.

  1. .gltf models cannot be loaded with the codes that I am using right now. It just console logs infinite lines of codes :frowning:

I am really confused. You mentionned the code was working before without textures and that it is now not working at all.

@RaananW tried your code and it is still not working with texture (same as before as I understand)

@DOEHOONLEE what is now not working which was ok prior to 5.22.1 ?

We really need to make the distinction between a regression and a none supported feature.

It doesn’t work because we are trying to use the Image object, which doesn’t exist in node. If image doesn’t exist, we are trying to load the URL, but blobs can’t be “loaded”.

I am trying to debug this. But the code is running without an issue, so I am not sure what you mean when you say it doesn’t work in 5.22.1.

I am sorry I should have mentioned the whole history.

I originally tried loading a model with Babylon.js v4.2.0 then it was possible to

  1. successfully load a .babylon model, but textures were mapped wrong
  2. .gltf model could not be loaded

With 5.22.1 version,

  1. .babylon model is still loadable, but only when it does not have texture references
  2. loading .gltf is still not working