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?
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?
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.
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?
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();
// });
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
@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
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
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
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
My ultimate goal would be to make it work with .gltf model though.
So for example, if you replace the rootURL
and the fileName
with https://playground.babylonjs.com/scenes/Dude/Dude.babylon
which has textures
it wouldn’t work.
In @slin 's example as well, it seems to be working, but it also uses a model without texture mapping.
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
With 5.22.1 version,
The above code can load https://playground.babylonjs.com/scenes/Dude/Dude.babylon
?
No, but that’s because of a different reason (which I just found). To render images we are using createImageBitmap
which is not available in node. There is an open issue for that - Support `ImageBitmap` and `createImageBitmap` · Issue #876 · Automattic/node-canvas · GitHub
@sebavan - think we can somehow polyfill this function? maybe use ImageData instead of ImageBitmap when bitmap is not available?
*** EDIT
to be more exact - when the Image
html element is missing (as in Node.js), we are using createImageBitmap to generate a bitmap and use this data to create the texture. but since the function doesn’t exist it fails. This is a node-only issue, which we will need to see how we can address.