How to get skeleton Data?

Hello, I’m Hizard. I have a big problem.
The problem has occurred when applying animation to the toon shader.

  • Typically, the toon shader works well when the character is in a non-animated state.

3

  • However, when applying animation, the toon shader entity does not function as expected.

The toon shader takes the mesh instance from the existing entity and adds it as a child to a new entity.
So, I want to bring along skeleton data in this process to enable animations.

Is there a good way to achieve this?
Example Project : PlayCanvas 3D HTML5 Game Engine

Hi @Hizard,

I haven’t tried it myself but you can use the skinInstance property to get a reference to the original skin (animated skeleton) and add it to the second mesh instance added. I think afterwards both mesh instances will be animated from the same skeleton:

1 Like

Thank you. @Leonidas
I tried to this way. However, in the files I have, skinInstance is displayed as null.

...
...
        var edgeMesh = new pc.MeshInstance(mesh.node, mesh.mesh, edgeMat);
        edgeMesh.castShadow = false;
        edgeMesh.receiveShadow = false;
        edgeMesh.skinInstance = mesh.skinInstance;
        edgeMesh.setParameter("edgeSize", this.edgeSize);
        edgeMesh.setParameter("edgeColor", this.edgeColor.data);
        edgeMesh.updateKey();

        meshInstancesArray.push(edgeMesh);
        console.log(mesh.skinInstance, edgeMesh.skinInstance);
    }

5

I haven’t tested with other files, but ultimately, if there’s no skinInstance, animations might not work correctly, right?

Yeah I think they won’t. @mvaligursky how should we do this?

Ah, I see! It’s called “bind skin.”

I think mesh.skin needs to be assigned, and also meshInstance.skinInstance.

1 Like

Thank you @mvaligursky

...
    var renders = this.entity.render.meshInstances;
    for (var r = 0; r < renders.length; r++) {
        var mesh = renders[r];
        console.log(mesh); // Exist skinInstance
        console.log(mesh.skinInstance); // null
...

After checking the logs, I’ve noticed that simply outputting the mesh shows the skinInstance property. However, when I output mesh.skinInstance, it returns null.
Where is my skinInstance? :sob:

The issue I was encountering previously was due to the skinInstance being inaccessible because of a too quick initialization.

I switched to a post-creation calling method
but now I’m encountering a new issue called “skinInstance lock.”

It seems that this issue might be arising when assigning the existing skinInstance to a new meshInstance.

...
        var edgeMesh = new pc.MeshInstance(mesh.node, mesh.mesh, edgeMat);
        edgeMesh.castShadow = false;
        edgeMesh.receiveShadow = false;
        edgeMesh.skinInstance = mesh.skinInstance;  // This
        edgeMesh.setParameter("edgeSize", this.edgeSize);
        edgeMesh.setParameter("edgeColor", this.edgeColor.data);
        edgeMesh.updateKey();

Do you know of any known solutions for this issue?
@mvaligursky @Leonidas

Instead of trying to create / assign skin instances yourself, perhaps try to just assign a rootBone entity (which is the root of the skeleton) to the render component, that clones skin instances internally.

2 Likes

I’m so sorry to bother you. @mvaligursky
Maybe this is the last question.

...
    var clone = this.entity.clone();
    clone.setLocalScale(1,1,1);
    clone.name = 'clone';
    clone.removeComponent('script');

    for (var i = clone.children.length - 1; i >= 0; i--) {
        clone.children[i].destroy();
    }
    
    var renders = clone.render.meshInstances;
    for (var r = 0; r < renders.length; r++) {
        var mesh = renders[r];

        var newMaterial = mesh.material;
        newMaterial.chunks.lightDiffuseLambertPS = lightDiffuseToonPS;
        newMaterial.setParameter("texture_ramp", ramp);
        newMaterial.update();

        var edgeMat = newMaterial.clone();
        edgeMat.chunks.transformVS = transformToonEdgeVS;
        edgeMat.customFragmentShader = edgePS;
        edgeMat.cull = pc.CULLFACE_FRONT;
        edgeMat.update();

        mesh.material = edgeMat; // Lost skinInstance
        mesh.setParameter("edgeSize", this.edgeSize);
        mesh.setParameter("edgeColor", this.edgeColor.data);
        mesh.updateKey();
    }

    clone.render.rootBone = this.entity.render.rootBone;
    this.entity.addChild(clone);

I created the entity using a cloning method, but during the process of adding the material, the skinInstance seems to be lost. (I confirmed this through the logs.)

...
        mesh.material = edgeMat;
        mesh.skinInstance = this.entity.render.meshInstances[r].skinInstance; // Occur Lock issue.
        mesh.setParameter("edgeSize", this.edgeSize);
        mesh.setParameter("edgeColor", this.edgeColor.data);
        mesh.updateKey();
    }

    clone.render.rootBone = this.entity.render.rootBone; // Occur Lock issue.
    this.entity.addChild(clone);

Using skinInstance and rootBone together seems to trigger the skinInstance lock issue.
Is it natural for the skinInstance to disappear during the process of adding the material originally?

Your code seems fine, I don’t see any obvious issue, and I would not expect skinInstance to be lost when you set material.

Could you perhaps create a minimal project that can repro the issue so that we can have a look?

Yes, Here is project. PlayCanvas 3D HTML5 Game Engine

It is written in toon.js in the ToonShader folder.
Pressing the number 3 will trigger an error.

Hey … had a quick look, and I get the same problem (as expected), but I don’t have much time to debug this, as the code handling it is non-trivial under the hood.

What is it exactly you’re trying to do? Do you want to clone the whole character with different shader? Or do you want the same character but change its shaders? As it’s likely there is a simpler solution than this.

Thank you for taking a look at the project. @mvaligursky :grinning:

I believe what I want is to use the same character while only changing the shader.
Since I’m a beginner when it comes to shaders, I’ve adopted this script.

From briefly examining the code,

  • it seems to take the existing mesh instance and add a ramp texture to the material.
  • Then, it creates a new entity beneath it with the original material replaced by a black-filled one to implement an outline effect.

I have a general understanding of this process, but I don’t have the specifics.

Ultimately, if I can achieve the toon shading effect without complications, I think any method will suffice.

P.S. - Since there isn’t much time left before the mid-term deadline, if it takes too long, I plan to proceed without the outline effect. However, in the final result, I do want to apply the outline effect as well.