GLSL Skinning Big Bug!

Hi devs.

If there will be models with GLSL animation and without it, so there will be BIG BUG.

How to repeat the bug:

  • Open TestHWSkinning.java in the tests.
  • Add these lines:
    [java]
    public void simpleInitApp() {
    Spatial modelBug = (Spatial) assetManager.loadModel(“Models/Oto/Oto.mesh.xml”);
    modelBug.setLocalScale(0.1f);
    rootNode.attachChild(modelBug);

    [/java]

And GLSL Skinning will be broken.

The issue occurs because certain vertex buffers from the OTO model are shared across both hardware skinned and software skinned meshes. Since the SkeletonControl modifies the BoneIndex / BoneWeight vertex buffers depending on the skinning mode selected, it corrupts the data of other SkeletonControls which operate in a different skinning mode.

There are several solutions to this issue:

  1. For a particular model, use either hardware skinning or software skinning, but not both.
  2. When applying the modification to the mesh, do not modify the BoneIndex / BoneWeight vertex buffers but clone them prior to the modification. The disadvantage is that now, live switching between hardware and software skinning mode will leak vertex buffers, in addition, the switch has to occur for every model instance loaded which will be very slow.
  3. Add two new VertexBuffer types: BoneIndexHardware and BoneWeightHardware, which would contain direct buffers and will be used for hardware skinning only. These must be generated prior to the model being placed in the asset cache, as otherwise you will have the same issue as #2, that the buffers have to be generated for every model instance loaded.
  4. Add an additional field to VertexBuffer that would hold a "heap" version of the buffer, in addition to the "direct" version which is used for hardware skinning. This way the same VertexBuffer can be used for both hardware and software skinning.
  5. Implement software skinning in native / C++ code and not support it in Java. The heap version of the buffers is not needed since native code can access the direct buffers directly.
  6. Modify the software skinning code to read from direct buffers instead of heap buffers. This will slow down software skinning significantly due to additional direct -> heap copy operations.

So far I like #3 the best, since it requires the least intrusive core modifications than the other options, its also the least “hacky” option.

I also like #1, just force people to choose between software or hardware skinning for a particular model. You can still use software skinning on models with large number of bones, and use hardware skinning for less complex models.

1 Like

5 sounds sooooo good! :stuck_out_tongue:

IMO 1 would be the easiest way and would fit in 99% of the cases. (and 58 studies prove it).
The problem is that it feels unintuitive, specially for users that don’t even know that the buffer are shared.

1 Like

What if to make a global switcher to all SkeletonControls for the skinning? At present, i should switch the GLSL skinning to every SkeletonControl, that’s not so cool, imho.

We talked about it with Kirill and found another solution.
I’m taking care of this.

2 Likes
<cite>@nehon said:</cite> 5 sounds sooooo good! :p

IMO 1 would be the easiest way and would fit in 99% of the cases. (and 58 studies prove it).
The problem is that it feels unintuitive, specially for users that don’t even know that the buffer are shared.

Not sure is trolling day or what ? :smiley:
soooooo good…
and then 58 studies …?
Are you high at that moment dude? ;O

That was not trolling that was right on the matter :stuck_out_tongue:

@nehon said: We talked about it with Kirill and found another solution. I'm taking care of this.

Ok, cool!

I have another idea: possibly? the easiest solution is to make a Listener which will convert all SkeletonControls to GLSL/CPU?

Anyway, you know it better. :slight_smile:

I’ve just committed the fix.
It should work now. You can have 2 identical models and use HW for one and SW for the other.

3 Likes

Fast one ;p Thanks

<cite>@nehon said:</cite> I've just committed the fix. It should work now. You can have 2 identical models and use HW for one and SW for the other.

Nice, actually what is the solution now?

@Empire Phoenix said: Nice, actually what is the solution now?
Before we were using BoneIndex and BoneWeight buffers as non direct buffers for software skinning with usage CPUOnly. If hardware skinning was set on, the buffers were replaced by direct buffers with Static usage. Those buffers are shared across all the clones of the model. So that's why there was an issue. We went on solution #3, and created HW specific buffer type HWBoneIndex and HWBoneWeight. Those buffers are direct and initially created with empty data in the loading process so that they are placed into the cache of the asset manager. Then when hardware skinning is activated on one of the model, the HW buffers are populated with the boneIndex and BoneWeight buffers data. So Hardware and software buffers are never mixed up and you don't waste direct memory if hardware skinning is not used.

Some enhancements are possible. Software skinning uses bind poses buffer (for positions, normals and optionally tangents). Hardware skinning doesn’t need those buffers so we could have a way to initialize those buffers only if software anim is used…