Skinning and weights

This topic contains 7 replies, has 3 voices, and was last updated by  Crescent 5 years, 6 months ago.

Viewing 8 posts - 1 through 8 (of 8 total)
  • Author
    Posts
  • #30788

    Hello,

    I made an animation in Blender 2.60 and successfully exported it to POD. It uses weight based skinning.

    I loaded it into the Skinning Demo in the TrainingCourse folder.

    Everything works fine but I am having some oddities in the vertex positions. Vertexes positions are near to be correct.

    To obtain some detail I rotated some bones around their own axis. I’m not completely sure but it seems that this rotation is not well calculated by the vertex shader, or maybe ignored at all actually.

    Any suggestions?

    Thanks in advance for any help.

    R

    #35587

    With a better observation I saw that the problem might be where more than one bone has influence. I think the sum of the weighted bone matrices is not done properly in the vertex shader. Is this possible?

    My weights are normalized so that for every vertex the sum of bones’ influences is always 1.0.

    #35588

    Scott
    Moderator

    Hi,

     
    Does your POD file look correct in PVRShaman? Also, how many bone influences do you have per-vertex? The OGLES2 Skinning example is setup for 3 bone influences. On a similar note what matrix palette size did you use? Again, the example expects a maximum size of 8. If you have more influences or more matrices in your palette the example will need to be tweaked to support all the skinning information.
     
    Thanks,
     
    Scott
    #35589

    Here’s the code of the slightly modified vertex shader of the Skinning demo.

    See the two bold lines before, where the vertex position and normal is calculated from all the bones influencing it.

    /*

         If the current vertex is affected by bones then the vertex position and

         normal will be transformed by the bone matrices. Each vertex wil have up

         to 4 bone indices (inBoneIndex) and bone weights (inBoneWeights).

         

         The indices are used to index into the array of bone matrices

         (BoneMatrixArray) to get the required bone matrix for transformation. The

         amount of influence a particular bone has on a vertex is determined by the

         weights which should always total 1. So if a vertex is affected by 2 bones

         the vertex position in world space is given by the following equation:

         position = (BoneMatrixArray[Index0] * inVertex) * Weight0 +

                         Â (BoneMatrixArray[Index1] * inVertex) * Weight1

         The same proceedure is applied to the normals but the translation part of

         the transformation is ignored.

         After this the position is multiplied by the view and projection matrices

         only as the bone matrices already contain the model transform for this

         particular mesh. The two-step transformation is required because lighting

         will not work properly in clip space.

    */

    attribute highp   vec3 inVertex;

    attribute mediump vec3 inNormal;

    attribute mediump vec2 inTexCoord;

    attribute mediump vec4 inBoneIndex;

    attribute mediump vec4 inBoneWeights;

    uniform highp   mat4 MVPMatrix;

    uniform highp   mat4 ViewProjMatrix;

    uniform mediump vec3 LightDirModel;

    uniform mediump vec3 LightDirWorld;

    uniform mediump     int      BoneCount;

    uniform highp   mat4 BoneMatrixArray[8];

    uniform highp   mat3 BoneMatrixArrayIT[8];

    varying lowp    float LightIntensity;

    varying mediump vec2 TexCoord;

    varying mediump vec3 RSFactor;

    void main()

    {

         

         // On PowerVR SGX it is possible to index the components of a vector

         // with the [] operator. However this can cause trouble with PC

         // emulation on some hardware so we “rotate” the vectors instead.

         mediump ivec4 boneIndex = ivec4(inBoneIndex);

         mediump vec4 boneWeights = inBoneWeights;

         

         if (BoneCount > 0)

         {

              highp mat4 boneMatrix = BoneMatrixArray[boneIndex.x];

              mediump mat3 normalMatrix = BoneMatrixArrayIT[boneIndex.x];

         

              highp vec4 position = boneMatrix * vec4(inVertex, 1.0) * boneWeights.x;

              mediump vec3 worldNormal = normalMatrix * inNormal * boneWeights.x;

              

              // PowerVR SGX supports uniforms in the for loop and nested conditionals.

              // For performance reasons, the code below should be like this:

              for (lowp int i = 1; i < BoneCount; ++i)

              {

                        boneIndex = boneIndex.yzwx;

                        boneWeights = boneWeights.yzwx;

              

                        boneMatrix = BoneMatrixArray[boneIndex.x];

                        normalMatrix = BoneMatrixArrayIT[boneIndex.x];

              

                        if (boneWeights.x > 0.0)

                       {

                        position += boneMatrix * vec4(inVertex, 1.0) * boneWeights.x;

                        worldNormal += normalMatrix * inNormal * boneWeights.x;

                        // position += boneMatrix * vec4(inVertex, 1.0) * boneWeights.x; // ORIGINAL

                        // worldNormal += normalMatrix * inNormal * boneWeights.x; //ORIGINAL

                       Ã‚ }

              }

              // However this code causes a severe crash on PCEmulation

              // in some ATI hardware due to a very limited loop support.

              // If you are targeting SGX, please, modify the code below.

              

              gl_Position = ViewProjMatrix * position;

              // Simple diffuse lighting

              LightIntensity = max(0.0, dot(normalize(worldNormal), -LightDirWorld));

         }

         else

         {

              gl_Position = MVPMatrix * vec4(inVertex, 1.0);

              LightIntensity = max(0.0, dot(inNormal, -LightDirModel));

         }

         

         // Pass through texcoords

         TexCoord = inTexCoord;

         

         RSFactor = inNormal; // Test pass through

    }riccardo_CS2012-03-21 16:52:37

    #35590

    Thanks for your reply Scott.

    I am using 3 bones influences. Also when I export I specify 3.

    In PVRShaman I don’t see the model but I see it almost perfectly with animations and textures in the modded Skinning demo.

    I’m not sure I understood what the limitation of 8 refers to. Does that mean I cannot have more than 8 bones in my armature/skeleton?riccardo_CS2012-03-21 16:59:49

    #35591

    Scott
    Moderator

    When you say you specifiy 3 is this via the “Matrix palette size” field in the “Skin” box? If so, this is the field where you should put the limit of 8. You’re correct in a way that this limits the number of bones that affects a mesh to be 8 but your armature/skeleton can have more than that in Blender. The exporter will just split the mesh into batches.

    #35592

    Glad to say I found the problem. At one point during the my work I read around to try to export weights as RGBA and it kind of worked. I realized now that to export successfully from Blender (after having normalized weights) you need to export weights as unsigned bytes, normalized.

    I attach the TXT resulting from saving the POD file exporter parameters (using PVRGeoPOD 1.27 beta) that work perfectly for me with Blender 2.60.

    bFixedPoint=0

    bFlipTextureV=0

    bIndexed=1

    bUnpackMatrix=0

    bInterleaved=1

    bSortVtx=1

    bTangentSpace=0

    cS=2

    dwBoneLimit=3

    ePrimType=0

    eTriSort=1

    exportBoneGeometry=0

    exportControllers=1

    bIndexAnimation=0

    exportGeom=1

    exportMatrices=1

    exportMappingChannel=1

    exportMaterials=1

    bMerge=0

    exportNormals=1

    exportObjectSpace=1

    exportSkin=1

    exportSplines=0

    exportVertexColor=1

    fTangentSpaceVtxSplit=0.000000e+00

    bAlignData=0

    uiPadDataTo=4

    psVcOptUVW[0].eType=1

    psVcOptUVW[0].nEnable=131

    psVcOptUVW[1].eType=1

    psVcOptUVW[1].nEnable=131

    psVcOptUVW[2].eType=1

    psVcOptUVW[2].nEnable=131

    psVcOptUVW[3].eType=1

    psVcOptUVW[3].nEnable=131

    psVcOptUVW[4].eType=1

    psVcOptUVW[4].nEnable=131

    psVcOptUVW[5].eType=1

    psVcOptUVW[5].nEnable=131

    psVcOptUVW[6].eType=1

    psVcOptUVW[6].nEnable=131

    psVcOptUVW[7].eType=1

    psVcOptUVW[7].nEnable=131

    staticFrame=0

    sVcOptBin.eType=1

    sVcOptBin.nEnable=135

    sVcOptBoneInd.eType=13

    sVcOptBoneInd.nEnable=15

    sVcOptBoneWt.eType=15

    sVcOptBoneWt.nEnable=15

    sVcOptCol.eType=4

    sVcOptCol.nEnable=15

    sVcOptNor.eType=1

    sVcOptNor.nEnable=135

    sVcOptPos.eType=1

    sVcOptPos.nEnable=135

    sVcOptTan.eType=1

    sVcOptTan.nEnable=135

    Hope this helps someone. Cheers!!

    #35593

    Crescent
    Member

    It’s indeed helped ! I came to face the exact same problem,,

    <unsigned bytes, normalized>

    Thanks riccardo_CS !

Viewing 8 posts - 1 through 8 (of 8 total)
You must be logged in to reply to this topic.