ImportAsyncMesh on server side without scene

It looks like BABYLON.Tools.LoadScript is trying to use self which maybe doesn’t exist in this context? Looks like it was introduced with this PR: Enable use of Tools.LoadScript in a WebWorker by wmurphyrd · Pull Request #12884 · BabylonJS/Babylon.js (github.com)

1 Like

This should address it fix undefined self by sebavan · Pull Request #13061 · BabylonJS/Babylon.js · GitHub

3 Likes

Hello @M0D1 just checking in you need any more help?

I’m encountering a similar issue as @M0D1. I’m trying to import draco compressed GLBs in BJS serverside nodeJs. My code is almost the same as above except i’m using SceneLoader.LoadAssetContainerAsync.

I encounter:

ERROR	{
  err: n [RuntimeError]: Unable to load from <URL TO MY DRACO COMPRESSED GLB>: Cannot read property 'message' of undefined
      at p (/var/task/index.js:1:471752)
      at /var/task/index.js:1:472251
      at processTicksAndRejections (internal/process/task_queues.js:97:5) {
    errorCode: 3000,
    innerError: TypeError: Cannot read property 'message' of undefined
        at /var/task/index.js:1:4045235
        at processTicksAndRejections (internal/process/task_queues.js:97:5)
        at async Promise.all (index 0)
        at async Promise.all (index 0)
        at async Promise.all (index 0)
        at async Promise.all (index 0)
        at async Promise.all (index 0)
  }

Appreciate any advice you can share.

@Coffiend We need a repro or it will be hard to tell what is wrong.

2 Likes

I run by serverside job in AWS lambda nodeJs. Below is a code snippet without the lambda boilerplate that does the importing of GLBs. It works fine for importing normal GLBs. But throws error when importing draco compressed GLBs like the one I’ve provided in the code snippet.

import '@babylonjs/loaders';
import { Tools, DracoCompression, NullEngine, Scene, SceneLoader } from '@babylonjs/core';
import xhr2 from 'xhr2';

global.XMLHttpRequest = xhr2.XMLHttpRequest;

/**
 * Encounter issues when importing draco compressed GLBs.
 * Below is error message thrown.
 *
 * Unable to load from <URL TO GLB>: Cannot read property 'message' of undefined
 *
 */

Tools.GetAbsoluteUrl = (url) => {
	return url;
};

DracoCompression.Configuration = {
	decoder: {
		wasmUrl: 'https://cdn.jsdelivr.net/gh/google/draco/javascript/draco_decoder.js',
		wasmBinaryUrl: 'https://cdn.jsdelivr.net/gh/google/draco/javascript/draco_decoder.wasm',
		fallbackUrl: 'https://cdn.jsdelivr.net/gh/google/draco/javascript/draco_wasm_wrapper.js',
	},
};

const demo = async () => {
	const URL = 'https://mesh-anios-local-singapore.s3.ap-southeast-1.amazonaws.com/calender-draco-compressed.glb';

	const engine = new NullEngine();
	engine.enableOfflineSupport = false;
	engine.doNotHandleContextLost = true;
	const scene = new Scene(engine);

	const splitUrl = URL.split('/');
	const filename = splitUrl.pop();
	const rootUrl = splitUrl.join('/');
	const assetContainer = await SceneLoader.LoadAssetContainerAsync(`${rootUrl}/`, filename, scene);
	console.log(assetContainer.geometries);
};

demo();

Are you able to repro locally with a node server? If so, can you set up a repo or a zip so we can try?

I had trouble getting BJS running locally in node server. It had already took me a day of tinkering to get BJS running on AWS lambda. And so I created a repo that will deploy the aws lambda with BJS code and it reproduces the issue as I am encountering it for my project.

You can pull here. You’ll need to install aws-cli and add your aws creds. It’ll deploy the lambda to N. Virginia region. You can trigger the lambda via the lambda dashboard and you’ll see the error in the logs.

Sorry, that will be hard to debug. We need a local repro. I’m not sure Draco will work properly in a node environment. I’m not sure anyone has tried.

Ok. Let me try to get aws lambda running locally. I believe there was a way to do this.

Would you or anyone have a link to a repo for BJS running in a nodejs server (excluding draco)? Just getting BJS working in nodejs and webpack is a challenge. Getting transpile issues, etc. I can then use that to add in my import demo to reproduce the issue.

I don’t, but someone must have done this already. Maybe @RaananW knows.

We don’t have a node.js example, but it is on the todo list for sure (node and browsers templates). Maybe you can share your project or show the errors you are encountering, this way it will be simpler to help

Managed to get a nodejs express running with BJS. I’ve also reproduced my issue. See here. You’ll need to be using node v12 to get webpack to comply to run the server locally. Look forward to any advice/BJS fixes that can help.

Do you mean to say it will work with node 12+, or just with node 12?

Sorry seems I lied. Node v14 works fine as well. I’ll update the README accordingly.

1 Like

The error seems to be related to this:

maybe @bghgary can comment on the missing primitive? might it be an issue when loading the mesh itself?

It’s noteworthy to mention that the GLB is able to import fine into BJS sandbox.

1 Like

Thanks for the repo. I debugged a bit and found two issues:

  1. LoadScriptAsync is not properly capturing the error message (exception will be undefined in this case) and thus calls the reject with an undefined value. This causes the error message reported above instead of the real error since the error handler is trying to access the message property of the error argument which is undefined. I have a local fix for this.
  2. LoadScript is required by the Draco glTF extension to load the Draco WebAssembly and scripts, but the implementation of LoadScript does not handle a node.js environment. I’m not sure what the best way is to handle this one. @RaananW/@sebavan Any thoughts?

I assume this is because we don’t eval but add a script tag (which cannot be done in node.js). I am not too happy about eval-ing it, so we’ll have to come up with a smarter way of doing it.
As a follow up - if I am seeing this correctly, there is no way to pre-load the script. Will that be an acceptable solution? For example - when in node.js, the dev will use fs (or require?) to load both the .js and the wasm file (which should be loaded a little differently) and babylon will use those?