Cannot save and load Skeleton

I’m tried different ways to save a skeleton, but I cannot get any of them to work

In all cases, saving seems to work just fine and file sizes appear more-or-less ok, but I cannot load what was saved

  1. Saving to using native SceneSerializer.Serialize works,
    But when loading nothing is shown
    And nodes as seen in inspectors are definitely not in correct relationship
    See attached image - left is original and right is after load from saved serialized scene

  2. Saving using either GLTF2Export.GLBAsync or GLTF2Export.GLTFAsync works,
    But when loading I get runtime error

  Uncaught (in promise) RuntimeError: Unable to load from ./assets/test.glb: Cannot read properties of undefined (reading 'length')
    at RuntimeError2.BaseError2 [as constructor] (error.ts:6:1)
    at new RuntimeError2 (error.ts:71:9)
    at errorHandler (sceneLoader.ts:688:46)
    at sceneLoader.ts:745:21

Full reproduction:
(sorry, cant place it as PG as it requires load/save from filesystem, but example is pretty much trivial)
(note: Exactly the same behavior using SceneLoader.LoadAsync)

import * as BABYLON from '@babylonjs/core';
import '@babylonjs/inspector';
import { GLTF2Export } from '@babylonjs/serializers';

async function saveBabylon(s: BABYLON.Scene) {
  const serializedScene = BABYLON.SceneSerializer.Serialize(s);
  const strMesh = JSON.stringify(serializedScene);
  const blob = new Blob([strMesh], { type: 'octet/stream' });
  const objectUrl = URL.createObjectURL(blob);
  const link = window.document.createElement('a');
  link.href = objectUrl;
  link.download = 'test.babylon';
  const click = document.createEvent('MouseEvents');
  click.initEvent('click', true, false);
  link.dispatchEvent(click);
}

async function main() {
  // simplest scene setup
  const canvas = document.getElementById('canvas') as HTMLCanvasElement;
  const engine = new BABYLON.Engine(canvas, true);
  const scene = new BABYLON.Scene(engine, {});
  scene.debugLayer.show({ embedMode: true, overlay: false, showExplorer: true, showInspector: true });
  const camera = new BABYLON.ArcRotateCamera('camera', -Math.PI / 2, Math.PI / 2.5, 3, new BABYLON.Vector3(0, 0, 0), scene);
  camera.attachControl(canvas);
  const light = new BABYLON.HemisphericLight('light', new BABYLON.Vector3(0, 1, 0), scene);
  light.diffuse = BABYLON.Color3.FromHexString('#FFFFFF');
  engine.runRenderLoop(() => scene.render());

  // code used to save babylon, glb and gltf:
  /*
  await saveBabylon(scene);
  const glb = await GLTF2Export.GLBAsync(scene, 'test', {});
  glb.downloadFiles();
  const gltf = await GLTF2Export.GLTFAsync(scene, 'test', {});
  gltf.downloadFiles();
  */

  // loading original works just fine
  // const res = await BABYLON.SceneLoader.ImportMeshAsync('', './assets/', 'dummy3.babylon', scene);

  // loading serialized scene doesnt fail, but nothing shown
  // const res = await BABYLON.SceneLoader.ImportMeshAsync('', './assets/', 'test.babylon', scene);

  // fails with runtime error
  // const res = await BABYLON.SceneLoader.ImportMeshAsync('', './assets/', 'test.glb', scene);

  // fails with runtime error
  // const res = await BABYLON.SceneLoader.ImportMeshAsync('', './assets/', 'test.gltf', scene);
}

window.onload = main;

Environment: BabylonJS 5.0.0-rc.1 with Chrome 99

Screenshot from inspector views of original skeleton and one that was saved using serialization and then loaded back in:

@bghgary could you have a look ? I wonder if it might be related to the latest skeleton changes ?

@vladmandic You should be able to set up a playground for this. Does it not repro if you load from a url? If not, can you please provide which asset you are loading? Is it dummy3.babylon?

EDIT: You can load dummy3.babylon by using this url in the playground ./scenes/dummy3.babylon

yes, that’s the same dummy3.babylon - issue is not loading original (that works just fine), but saving it (both using serialization or using export to gltf/glb) and then attempt to load a newly saved one - and that i cannot do in PG.

at the very least, you can see in inspector output that mixamorg:Skin node has incorrect parent set
and i don’t know what to make out of runtime error when loading gltf/glb

@vladmandic : I don’t know whether this is relevant to your problem, but there are reports that the naming of bones and meshes like "mixamo:"xxx can cause problems with game engines such as the Godot engine. There are scripts to remove “mixamo:” from names.

I can give you a rigged character without “mixamo” to try out your code if you want.

Stay Safe, gryff :slight_smile:

@gryff one of main reasons why i was loading a skeleton and trying to save it is to edit node names of different skeletons so they all have same naming convention and i don’t have to do bunch of stuff if i want to change the skeleton used in app.

but saving skeleton from babylonjs seems to be broken at the moment.
i’m editing in blender now and exporting to glb, seems to be working just fine.

1 Like

@vladmandic : As you work with Blender here is a link to the renaming script for Blender - takes out all the “mixamo:” characters :

Renaming Script

You might find it useful someday.

Stay Safe, gryff :slight_smile:

1 Like

Yes, I understand that. I’m saying this only because you say you can’t do this with the playground, but it seems like you can.

I can’t repro the SceneSerializer issue. Using this PG and loading the resulting downloaded file in the sandbox, it looks fine to me.

For glTF, I can repro with this PG. I’ll see what I can find.

1 Like

For glTF, this problem repros in 4.2 also, so I don’t think this is a regression.

EDIT: This is expected for now. The glTF exporter doesn’t support this right now. See the console log:

Exporting a bone without a linked transform node is currently unsupported

I will fix the runtime error, that shouldn’t happen.

@bghgary

I’m saying this only because you say you can’t do this with the playground, but it seems like you can.

sorry :frowning:

I can’t repro the SceneSerializer issue. Using this PG and loading the resulting downloaded file in the sandbox, it looks fine to me.

weird - i definitely see that some nodes do not have their parent set correctly.

Exporting a bone without a linked transform node is currently unsupported

i dont see that in the console log?
anyhow, so thats a limitation of gltf exporter - basically it doesn’t work with most of skeletons (i tried 3 different ones)?

I will fix the runtime error, that shouldn’t happen.

thanks!

From the SceneSerializer PG above:
image

Taking the result test.babylon file and loading in the sandbox:
image

Clicking the link I sent for glTF. This is in the console:

The glTF exporter can only handle loaded glTF files at the moment. I don’t know if I would say non-glTF skeletons are most skeletons. Please file a feature request if you would to see this work for non-glTF skeletons.

PR: Prevent exception when glTF has empty joints array by bghgary · Pull Request #12114 · BabylonJS/Babylon.js (github.com)

From the SceneSerializer PG above:
Taking the result test.babylon file and loading in the sandbox:

I must be doing something wrong, I’ll verify it tomorrow - thanks.

Clicking the link I sent for glTF. This is in the console:

Silly me, I have console setup to show info+error, but not warning levels as chrome can get annoying there.

The glTF exporter can only handle loaded glTF files at the moment.

When you put it that way, I’m ok with that. Is that documented anywhere?

1 Like

I’m not sure, but I don’t think so. Do you want to contribute? :slight_smile:

fair point :slight_smile: