BJS Imports some GLBS with Multiple Duplicate Skeletons, while Three jsEditor and Blender Sees One?

So why does Babylon parse what blender would see as an Armature Modifiers as a new Armature?
image

When something like this gets exported even though its using one skeleton babylon will make multiple skeletons for it instead of just pointing to the skeleton it should.

Even if a mixamo mesh has a Armature Modifier we make multi skeletons.

This is not correct. We have GLBs being imported with like 7-8 skeletons on a single entity and that is not right.

An Armature Modifiers should be seen as just a pointer to a skeleton Im not sure what the data in the BLG is that handles this but if Blender handles it this way, BJS should as well.

Just to be clear, are you saying there are 2 skeletons in the .JSON export file, or it is a result of the load?

The exporter will use the findArmature() method during mesh processing so that the mesh need not be parented to an armature, as you are showing. However, that is not when the armature is captured.

There is a separate loop through all the objects just searching for Armatures. I do not see how an armature could be done more than once. If more than one skeleton is exported are you positive that you do not have multiples in Blender? If you do, the names will be different in the log file, as Blender does not allow duplicate names.

Check / post your export log file.

Would the glb file help?
Just to clarify though bjs is making multiples of the same skeleton.

So like for a character who in blender is setup with like
Body -> real armature
Shirt -> Armature Modifier

When exported as a glb and imported into babylon we end up with 2 identical skeletons. This then repeats for how ever many Armature Modifiers there are.

The Armature Modifier is just a reference to an existing skeleton. Im not sure how that data looks in the gltf format, but how do they establish that its a link and not another skeleton?

Not to me I’m out. The problem is downstream or GLB then. My guess is that is a GLB exporter problem. You see there is a reason I process armatures in a separate loop.

If you know how to import the to threeJS sandbox, you can determine where. My money is on the exporter being the problem. An importer would just not be able to make that up.


image

Three Editor makes 1 skeleton everything is as it should be.

That means the BJS GLTF importer isn’t working as it should. Currently multiple skeletons are made but the bones all link to the same transform nodes :thinking:

Its kinda odd looking at the data that is coming in. For sure shows that there are 4 armatures, but that is not correct… hmmm.

I am using the alien.glb as a base now.

Just verified that alien.glb comes into BJS as 4 skeletons. While in blender and Three.js Editor it comes in as one.

What are we doing different?

Must be in the data, or how ever the person who exported did it I am guessing. Because when I exported it from Blender I got one skeleton… hmmm this is odd because why would Blender see it as one initially and BJS only see it that way after I re-export it?

Yea, well it still doesn’t change the fact that BJS wrongly imports multiple skeletons for certain GLBs regardless of how it is exported, while ThreeJS doesn’t have this issue :confused:

What makes you think there’s a single skeleton in 3js?

Your screenshot shows that there is a single bone hierarchy, so no bone duplication. That’s the same thing in Babylon, you have a single bone hierarchy, which are represented by transform nodes in Babylon.

For eg, for the alien that has 4 skeletons as you mentioned:

The Root => Neck => … hierarchy is not duplicated.

Now back to the skeletons.

I have modified a 3js sample to count the number of different skeletons used by alien.glb. I simply did this:

const skeletons = [];

gltf.scene.traverse( function ( child ) {
    if ( child.isMesh ) {
        if (skeletons.indexOf(child.skeleton) < 0) {
            skeletons.push(child.skeleton);
        }
    }
} );

console.log(skeletons.length);

So, it is counting the number of different skeletons: if a skeleton is shared, it is counted once only.

The number displayed is 8, which is the same as the number of skinned mesh: so there is a different skeleton for each mesh.

In Babylon for this very same scene, there are only 4 different skeletons (as you can see in the screenshot above) because some are shared among multiple meshes. As a matter of fact, if you look at the json code of the alien gltf file, you can see there are 4 entries in the skins node: so I would say Babylon is right in this matter => 4 skins = 4 skeletons.

If you load the alien.glb file in Blender and re-export it, the new file has a single entry in the skins node of the gltf file: so you get a single skeleton in Babylon (and still 8 in 3js). Now, why Blender does that I don’t know, but on Babylon side everything appears to be ok to me.

[EDIT]
What may have confused you is that:
image
For gltf/glb files, those bones are only placeholder for the transform nodes: each bone link to a transform node, the bone itself does nothing and simply copy the transform from the transform node.
[/EDIT]

We actually came to this same conclusion yesterday about the data. After we tested that Three in fact does have the same skeleton count as BJS and I discovered the same info about exporting from blender on those questionable files.

Now we are trying to figure out what is the extra step that Blender takes to narrow it down to one skeleton? We are working on an animation editor and having multiple skeletons (in one of our glbs it makes 7 identical skeletons with 64 some bones.) will break a lot of features. What extra interpolation is happening for them to get seen as Skeleton Modifiers in Blender? If we can figure out how that does that, then we can effectively merge the skeletons references.

Thank you btw @Evgeni_Popov for your write up.

I don’t know what an armature modifier is, but it seems Blender creates one when a skeleton is a subset of another skeleton in the gltf file. For the alien case, the skins are defined as:

  "skins": [
    {
      "inverseBindMatrices": 79,
      "joints": [
        16,
        15,
        14,
        13,
        9,
        10
      ]
    },
    {
      "inverseBindMatrices": 80,
      "joints": [
        16,
        15,
        14,
        13
      ]
    },
    {
      "inverseBindMatrices": 81,
      "joints": [
        9
      ]
    },
    {
      "inverseBindMatrices": 82,
      "joints": [
        10
      ]
    }
  ]

So, skins 1/2/3 are a subset of skin 0 because all nodes used by the joint collections of skins 1/2/3 are in the joints collection of skin 0.

However, for this to be exported as a single skeleton, I think all the armature modifiers must actually not modify the bones / the animations, else a given node (bone) may animate differently depending on the skeleton it is used by. Also, I think all the inverseBindMatrices must be the same for the corresponding nodes, else a single skeleton can’t be exported.

1 Like

Ok cool, that gives me something to dig into thank you.

From a Blender point of view, it keeps a list of all armatures, separate from any modifiers. If only one armature is created, then there is always just one.

A modifier is set of directions of something an object has running against it. There are dozens of kinds. An armature modifier is one that can be added only to mesh objects. All this modifier type does is point out that this mesh is to be deformed by an armature using the weights of each vertex group. The modifier holds the armature to use.

armatureMod

The mesh which has this modifier is to be deformed the armature, “mYArmature”. Every mesh, which is to be deformed in this way, will have its own modifier. It really just a pointer.

That said, I really do not understand

Now we are trying to figure out what is the extra step that Blender takes to narrow it down to one skeleton?

If you are talking about what Blender does when it imports a .GLB files and one creates one skeleton given a file like the one you have, then that makes sense. Just look at the GLB importer source. Here is the link to the import source directory.

FYI: I just started my own BJS IK editor in the last 2 days. Trying to move that part from Blender directly into webGL. I am not using GLTF nor JSON formats for source data. Both are too complicated, not OO, and I am not following anyone else’s rules.

1 Like

so when Blender imports the FBX file, it stores all the extra skin data as armature modifiers. Then when the scene is re-exported as a GLB, this GLB is parsed by BJS as containing only 1 armature. We’re trying to figure out why (and how) Blender takes these armature modifiers and outputs just one skeleton.

image

I would like to just say as a closing note on this topic, my good buddy here at Pixcap did some @mrlooi cool coding and was able to get even fringe examples to get merged down into one skeleton. So my question still kinda is out there why we dont inherently do something like this?

animations work and as far as we can tell nothing is lost by doing this. Would really clean up some imports.

Contributions are always welcome and will be merged if the team finds them somehow valuable!

Adding also @bghgary and @Drigax here to see how to turn this in :slight_smile:

Are we saying to merge skeletons on import or export? I don’t think we should do any processing on import since that goes against what glTF is meant to do.

Then why does blender do it, they definitely process the skeletons an additional step we are not doing. I cant think of one user who wants 25 duplicate skeletons coming in when one does the same thing?