Hardware skinning - strange effect

Everything is ok w/o hardware skinning.

After enabling it I have very strange effect. Mob looks wrong, so far I’m unable to find the reason. Any idea?

    SkeletonControl sc = spatial.getControl(SkeletonControl.class);
    if (sc != null) sc.setHardwareSkinningPreferred(true);

Hello,

I can’t reproduce that.
=> maybe the problem comes from the model ?

EDIT:
@FrozenShade : after double checking sc.isHardwareSkinningUsed() always returns false. Sorry I’m not sure I’ll be able to help :frowning:
EDIT (2nd) : after triple checking it works on one of my models, but it looks as usual.

I’ll ask our graphics guy to upload the model so you can test.

Is the skeleton shared between several models?

At the moment only one instance of a monster is present in 3d models tree.
But the model is loaded twice from assetManager: first time for initialization, where I read constant values (animation times etc) for my internal purposes. After that the model is loaded once again and placed on 3d scene.

Do you by any chance play the animations before setting the hardware skinning?
I had this kind of issues when switching on the fly between software and hardware skinning, because software skinning actually alters the position buffer.

Probably not, but I must check it, to be 100% sure. I’ll do it when I’ll be back at home. Thank you.

It might be a bit hacky but maybe calling

skeleton.reset();
skeletonControl.update(0.016f);

before enabling the hardware skinning might do the trick.

I’ll try that. What meas that 0.016f, is that some ‘magic value’ ?

Approximately the tpf with a frame rate of 60. It’s just to not call it with 0 because it could get wonky.

Is the skeleton shared between several models?

Is that a problem ? If so, why ?
I couldn’t find much information other than the source code about hw skinning. I’m interested by any documentation on the subject.

It shouldn’t but it could be.

Well that’s the question we’d have to answer if it was the issue :stuck_out_tongue:

In short : software skinning is done on the CPU by computing each vertex transformation from the bone transformations. Then those transformations are applied to the position buffer of the mesh.
That last operation can be expensive especially if you have a lot of skinned models in your scene.

Hardware skinning consists on computing the transforms and sending them to the vertex shader and transform the vertex there before projecting it to screen. It’s a lot faster, but uses a fair amount of the allowed uniforms that you can send to a shader program.

Thank you for the answers @nehon

I may provide models for which sc.isHardwareSkinningUsed() always returns false but I’m not sure it’s related to FrozenShade’s problem.
They all share the fact that they were made using makehuman et partially animated using makewalk …
So if you have some time to look at those models I’d gladly provide them to you. If you have no time or no will to look at them it’s fine I’ll stick to soft skinning.

ha …time…
I may provide some tracks to follow though.
I think that when you try to enable HW skinning and that it fails, it ouput a warning with some relevant information. you have to scrutinise the log.

What can happen is that your hardware doesn’t support the extensions needed for HW skinning (but that’s probably not the case since some of them are working).
Another track can be that there are too much bones in the skeleton and that that would generate too much data to be sent to the shader. Also not sure, but the number of vertices could be a problem too (if there are too much).
Maybe @Momoko_Fan can comment on that he knows a fair deal about HW skinning in JME.

Ok I see.
Now that I understand it a bit better I’ll take a deeper look at my models when I’ll have time too.
People think money is the rarest resource but time is even more rare :smile: Too bad we haven’t yet reverse engineered space-time.

@FrozenShade: I may try your model if you want me to do so but I can’t guarantee it will help.

Nah, I think it’s generally accepted that time is really the only resource. All life is about buying time or using time. Money is potentially the grease or catalyst but really it’s all about manipulating the finite resource of time we are given.

…oops, got deep there for a sec.

https://drive.google.com/open?id=0B2z_kShVsBHBMGZyWjZHYWUxVlU&authuser=0

Our testrobo project file. License CC-BY :stuck_out_tongue:

Before import, delete EdgeSplit Modifier - importer dont like it. I going to remove IK bones before final import for monsters. Workaround for IK bones and importer - it dont see deformations: keying visual position of yellow bones (in IK chain) :smiley:

@nehon it does not changed anything. I tested it and I’m sure that I’m enabling HW skinning at the very beginning, before any animation is played.

EDIT: important question: does the animation animates when the geometry is outside camera’s view? I found that there is a problem, shadows on walls ‘jumps’ when I don’t look at the mob but they are ok when I look at the animating mob.

EDIT2: seems like it is true. When the mob is transformed by me (my own control changes its rotation) I can see the change on shadow. But when the mob does only the animation in loop, without any transformations, the shadow stands still… I really need a good workaround, even dirty one. Any idea?

EDIT3: I did the trick… In my own MainShadowRenderer (where I collect all other shadow renderers) I add a code in the PostQueue:

    for (int i = 0; i < occluders.size(); i++)
    {
        Geometry g = occluders.get(i);
        if (g.getName().charAt(0) != '_') continue; // Ugly test if it is an animated geometry
        
        //TODO: test if it is close enough to the player's cam
        Node n = g.getParent();
        SkeletonControl sc = n.getControl(SkeletonControl.class);
        if (sc == null) continue;
        
        sc.render(_renderManager, _viewPort);
    }

Say, how much dirty it is, and any idea to make it a bit more clean?

By the way, this is a great use-case for user data.
if (g.getUserData(“animated”) == null ) continue;

…somewhere else:
g.setUserData(“animated”, true)

Yes, I know :wink:
But this one is much faster.
I’m using ‘_’ prefix in few other places in the code that executes every frame several times.

From the very beginning I try to optimize everything and I don’t want to waste cpu time. Even some of my nodes does not pass updateLogicalState/updateGeometricState to their children.