Hi. Sorry, if this has been covered elsewhere. I’m trying to use the AssetManager in a node app (with NullEngine).
My test code is the example code from the NullEngine documentation plus a few lines to import a file with the asset manager.
Runs successfully in node without those lines.
Calling aman.load() causes this error:
E:\dev\bab\sand-box\node_modules\xhr2\lib\xhr2.js:281
throw new NetworkError(Unsupported protocol ${this._url.protocol});
^
Error
at XMLHttpRequest.send (E:\dev\bab\sand-box\node_modules\xhr2\lib\xhr2.js:281:19)
at e.send (E:\dev\bab\sand-box\node_modules\babylonjs\babylon.js:16:602616)
at s (E:\dev\bab\sand-box\node_modules\babylonjs\babylon.js:16:58518)
at p (E:\dev\bab\sand-box\node_modules\babylonjs\babylon.js:16:58526)
at Function.e.LoadFile (E:\dev\bab\sand-box\node_modules\babylonjs\babylon.js:16:58754)
at t._loadFile (E:\dev\bab\sand-box\node_modules\babylonjs\babylon.js:16:319633)
at t.runTask (E:\dev\bab\sand-box\node_modules\babylonjs\babylon.js:16:2149344)
at t.e.run (E:\dev\bab\sand-box\node_modules\babylonjs\babylon.js:16:2148097)
at e._runTask (E:\dev\bab\sand-box\node_modules\babylonjs\babylon.js:16:2153778)
at e.load (E:\dev\bab\sand-box\node_modules\babylonjs\babylon.js:16:2154548)
Here’s the test code:
//
// Copy-pasted from the NullEngine documentation
// except for the last three lines.
// The line (aman.load()) causes an ‘Unsupported protocol’ error
// when this runs in node.
//
var BABYLON = require(“babylonjs”);
var LOADERS = require(“babylonjs-loaders”);
global.XMLHttpRequest = require(‘xhr2’).XMLHttpRequest;
var engine = new BABYLON.NullEngine();
var scene = new BABYLON.Scene(engine);
var light = new BABYLON.PointLight(“Omni”, new BABYLON.Vector3(20, 20, 100), scene);
var camera = new BABYLON.ArcRotateCamera(“Camera”, 0, 0.8, 100, BABYLON.Vector3.Zero(), scene);
BABYLON.SceneLoader.ImportMesh(“”, “https://playground.babylonjs.com/scenes/”, “skull.babylon”, scene, function (newMeshes) {
camera.target = newMeshes[0];
console.log("Meshes loaded from babylon file: " + newMeshes.length);
for (var index = 0; index < newMeshes.length; index++) {
console.log(newMeshes[index].toString());
}
BABYLON.SceneLoader.ImportMesh("", "https://www.babylonjs.com/Assets/DamagedHelmet/glTF/", "DamagedHelmet.gltf", scene, function (meshes) {
console.log("Meshes loaded from gltf file: " + meshes.length);
for (var index = 0; index < meshes.length; index++) {
console.log(meshes[index].toString());
}
});
console.log("render started")
engine.runRenderLoop(function() {
scene.render();
})
});
// try asset manager
var aman = new BABYLON.AssetsManager(scene);
var specTask = aman.addTextFileTask(‘load-task’, ‘./models/LoaderSpec/LoaderSpec.json’);
aman.load();
What am I doing wrong?
Thanks for any advice.
OK. After looking more closely at the error, it seems like this is not an AssetManager problem or a Babylon problem. It’s a problem with my xhr2 library: it doesn’t support the ‘file’ protocol. (Indeed the README mentions this specifically.)
I need to find another xhr2 library or setup some work-arounds to use when running in node.
1 Like
So which XHR library did you use? Im having the same issue
Unfortunately, I just went with a work around. A wrapper class around AssetManager that re-formats file paths to http. And my node entry point script starts up a local express http server to serve itself the local files.
Here’s the wrapper class:
import { AssetsManager, MeshAssetTask, Scene, TextFileAssetTask, BinaryFileAssetTask, Nullable, TextureAssetTask, AbstractAssetTask } from "babylonjs";
//
// Wrapper around an AssetManager
// that reformats file system urls
// to http when in 'nodeMode'.
// Running in node, the 'xhr2' library doesn't handle
// file protocol.
// Just passes on the url if not in nodeMode.
//
export class MNodeWorkAroundAM
{
private am : AssetsManager;
private nodeMode : boolean = false;
private serverUrl : string | undefined;
private static get AssetsRootPath() : string { return "assets"; }
constructor(
scene : Scene,
nodeMode ? : boolean,
serverUrl ? : string
) {
this.am = new AssetsManager(scene);
if(nodeMode) {
this.nodeMode = nodeMode;
this.serverUrl = serverUrl ? serverUrl : "http://localhost:8000";
}
}
set onProgress(onProg : (remaining : number, total : number, task : AbstractAssetTask) => void) {
this.am.onProgress = onProg;
}
set onFinish(onFin : (tasks : AbstractAssetTask[]) => void) {
this.am.onFinish = onFin;
}
addTextFileTask(taskName : string, url : string) : TextFileAssetTask
{
return this.am.addTextFileTask(taskName, this.FormatURL(url));
}
addBinaryFileTask(taskName : string, url : string) : BinaryFileAssetTask
{
return this.am.addBinaryFileTask(taskName, this.FormatURL(url));
}
addMeshTask(taskName : string, meshNames : Nullable<string[]>, rootUrl : string, sceneFilename : string) : MeshAssetTask
{
return this.am.addMeshTask(taskName, meshNames, this.FormatURL(rootUrl), sceneFilename);
}
addTextureTask(taskName : string, url : string, noMinimap ? : boolean, invertY ? : boolean, samplingMode ? : number) : TextureAssetTask
{
return this.am.addTextureTask(taskName, this.FormatURL(url), noMinimap, invertY, samplingMode);
}
load() : AssetsManager
{
return this.am.load();
}
static AddAssetRootToPath(path : string) : string {
return `${MNodeWorkAroundAM.AssetsRootPath}/${path}`;
}
private FormatURL(url : string) : string
{
// if 'node-mode' add server url to path type urls
let fullPath = MNodeWorkAroundAM.AddAssetRootToPath(url);
if(this.nodeMode) {
if(url.indexOf('http') !== 0) {
return `${this.serverUrl}/${fullPath}`;
}
}
return fullPath;
}
}