1
\$\begingroup\$

I'm having troubles with properly animating a skin mesh from an .fbx file. I feel like the issue is in the shader, but not sure what is going on. All I know is that I am getting unexpected results where it feels like I'm providing all of the proper information.

If i use a single bone for all positions instead of the ones that are passed in the layout location, it puts the vertices in the right spot, so the calculations are correct.

From the looks of everything, my bone calculations are correct, bone ids are loaded, and weights are loaded fine, but it seems like they don't keep their values.

What it seems like is happening: BoneIDS and/or BoneWeights are being zeroed or set to something else.

For reference:

typedef struct sFloat4
{
    float x, y, z, w;
} sFloat4;

typedef struct sInt4
{
    int x, y, z, w;
} sInt4;

typedef struct sVertex_p4t4n4b4i4
{
    sFloat4 Pos;
    sFloat4 TexUVx2;
    sFloat4 Normal;
    sInt4 BoneIDs;
    sFloat4 BoneWeights;
} sVertex_p4t4n4b4i4;

and

unsigned int totalVertBufferSizeBYTES = numIndicesInIndexArray * sizeof ( sVertex_p4t4n4b4i4 ); ;
glBufferData ( GL_ARRAY_BUFFER, totalVertBufferSizeBYTES, pTempVertArray, GL_STATIC_DRAW );
CheckGLError();

unsigned int bytesInOneVertex = sizeof( sVertex_p4t4n4b4i4 );
unsigned int byteOffsetToPosition = offsetof( sVertex_p4t4n4b4i4, Pos );        
unsigned int byteOffsetToUVCoords = offsetof( sVertex_p4t4n4b4i4, TexUVx2 );
unsigned int byteOffsetToNormal = offsetof( sVertex_p4t4n4b4i4, Normal );   
unsigned int byteOffsetToBoneIDs = offsetof( sVertex_p4t4n4b4i4, BoneIDs );
unsigned int byteOffsetToBoneWeights = offsetof( sVertex_p4t4n4b4i4, BoneWeights );

glEnableVertexAttribArray ( 0 );        // Position
glEnableVertexAttribArray ( 1 );        // TexCoord
glEnableVertexAttribArray ( 2 );        // Normal
glEnableVertexAttribArray ( 3 );        // BoneIDs
glEnableVertexAttribArray ( 4 );        // BoneWeights

glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, bytesInOneVertex, (GLvoid*)byteOffsetToPosition );
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, bytesInOneVertex, (GLvoid*)byteOffsetToUVCoords );
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, bytesInOneVertex, (GLvoid*)byteOffsetToNormal );
glVertexAttribPointer(3, 4, GL_INT, GL_FALSE, bytesInOneVertex, (GLvoid*)byteOffsetToBoneIDs );
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, bytesInOneVertex, (GLvoid*)byteOffsetToBoneWeights );
CheckGLError();

I have dumped all of the information into log files like this:

On mesh load: (V:ertex, T:excoord, N:ormal, W:eight, I:d)

V: ( -10.7595, -90.5606, 10.2667, 1)
T: ( 0.800398, 0.961321, 0, 0)
N: ( -0.43245, -0.568786, -0.699621, 0)
W: ( 1, 0, 0, 0)
I: ( 1, 0, 0, 0)
------------------------------------
V: ( -13.78, -90.5591, 15.3024, 1)
T: ( 0.791644, 0.936781, 0, 0)
N: ( -0.786336, -0.582521, -0.205779, 0)
W: ( 1, 0, 0, 0)
I: ( 1, 0, 0, 0)
------------------------------------
V: ( -12.0146, -80.7495, 15.3008, 1)
T: ( 0.842778, 0.927585, 0, 0)
N: ( -0.994609, 0.0540453, -0.0884974, 0)
W: ( 0.5, 0.5, 0, 0)
I: ( 0, 1, 0, 0)
------------------------------------
V: ( -12.0146, -80.7495, 15.3008, 1)
T: ( 0.842778, 0.927585, 0, 0)
N: ( -0.994609, 0.0540453, -0.0884974, 0)
W: ( 0.5, 0.5, 0, 0)
I: ( 0, 1, 0, 0)
------------------------------------
V: ( -9.78351, -80.4126, 10.7916, 1)
T: ( 0.84573, 0.957308, 0, 0)
N: ( -0.517826, -0.0239735, -0.85515, 0)
W: ( 0.5, 0.5, 0, 0)
I: ( 0, 1, 0, 0)
------------------------------------
...
...
...

Walk Animation @ 0.1 seconds.log

...
...
...
RigLArmPinky1
  Scaling: 0.999793, 1.00015, 1.00005
  Rotation: -0.00196581, -0.000597763, -0.301885, 0.953342
  Position: 11.2164, -0.0247269, -1.10963
>> [ Bone #35 ] 
    Global Transformation
     > Translation: 37.7533, 75.6701, 35.4029
     > Scaling: 0.999963, 1.00049, 1.00026
     > Rotation: 0.159073, 0.536706, 0.58563, 0.586242
--------------------
...
...
...
--------------------
RigRArmIndex2
  Scaling: 1.00019, 0.999862, 0.999948
  Rotation: 2.10373e-005, -4.84573e-005, -0.399209, 0.91686
  Position: 2.76004, 3.8147e-006, -9.53674e-007
>> [ Bone #20 ] 
    Global Transformation
     > Translation: -37.1777, 57.9378, -6.8726
     > Scaling: 1.00027, 1.00014, 0.999923
     > Rotation: -0.96948, 0.194101, 0.141847, 0.0482982
...
...
...

Pictures

If I use povided bone ids from the layout location: Using provided BoneIDs

--

If I use all bone ids as 20 position += BoneMatrices[20] * in_Position * in_BoneWeights[0];: Using all BoneID as 20

--

If I use all bone ids as 35 position += BoneMatrices[35] * in_Position * in_BoneWeights[0];: Using all BoneID as 35

Vertex Shader

#version 400

layout(location=0) in vec4 in_Position;   // x,y,z,1.0f
layout(location=1) in vec4 in_UV_x2;
layout(location=2) in vec4 in_Normal;     // x,y,z,0.0f
layout(location=3) in ivec4 in_BoneIDs;
layout(location=4) in vec4 in_BoneWeights;

out vec4 ex_Position;           
out vec4 ex_PositionWorld;
out vec4 ex_Normal;
out vec4 ex_UV_x2;
out vec4 ex_BoneWeights;
out vec4 ex_BoneIDs;

uniform mat4 RotationMatrix;
uniform mat4 ModelMatrix;
uniform mat4 ViewMatrix;
uniform mat4 ProjectionMatrix;

const int MAX_BONES = 100;
uniform mat4 BoneMatrices[MAX_BONES];
//uniform mat4 BoneRotationMatrices[47];

uniform bool bHasBones;

void main(void)
{
// Calculate MVP Matrix
    mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;

    if ( bHasBones == false )
    {
        gl_Position = MVP * in_Position;

        ex_Position = in_Position;
        ex_PositionWorld = ModelMatrix * in_Position;
        ex_Normal = RotationMatrix * normalize(in_Normal);
        ex_UV_x2 = in_UV_x2;

        return;
    }

    int BoneID0 = in_BoneIDs[0];
    int BoneID1 = in_BoneIDs[1];
    int BoneID2 = in_BoneIDs[2];
    int BoneID3 = in_BoneIDs[3];

// calculate positionworld  
    vec4 position = vec4(0.0f, 0.0f, 0.0f, 0.0f);
    position        += BoneMatrices[BoneID0] * in_Position * in_BoneWeights[0];
    position        += BoneMatrices[BoneID1] * in_Position * in_BoneWeights[1];
    position        += BoneMatrices[BoneID2] * in_Position * in_BoneWeights[2];
    position        += BoneMatrices[BoneID3] * in_Position * in_BoneWeights[3];

    gl_Position = MVP * position;
    ex_Normal = RotationMatrix * in_Normal;
    ex_Position = position;
    ex_PositionWorld = ModelMatrix * position;
    ex_UV_x2 = in_UV_x2;

    ex_BoneWeights = in_BoneWeights;
    ex_BoneIDs = in_BoneIDs;

    return;
}

If you need me to provide anything else, I am more than happy to post more code, pictures, or dump any information for you

Edit #1

So i'm working on the theory that the ids are getting altered (set to 0). What i did was this:

    int BoneID0 = in_BoneIDs[0] + 46;
    int BoneID1 = in_BoneIDs[1] + 46;
    int BoneID2 = in_BoneIDs[2] + 46;
    int BoneID3 = in_BoneIDs[3] + 46;

// calculate positionworld  
    vec4 position = vec4(0.0f, 0.0f, 0.0f, 0.0f);
    position        += BoneMatrices[BoneID0] * in_Position * in_BoneWeights[0];
    position        += BoneMatrices[BoneID1] * in_Position * in_BoneWeights[1];
    position        += BoneMatrices[BoneID2] * in_Position * in_BoneWeights[2];
    position        += BoneMatrices[BoneID3] * in_Position * in_BoneWeights[3];

That has the same result as the first picture. If I add 47 (The size of the bone array) it throws INVALID_OPERATION. Does that prove that the ids are not being set properly then?

Edit #2 Changed sVertex_p4t4n4b4i4 to be all floats, and changed layout locations to be vec4 instead of ivec4. Casted the ids to be ints, and everything works perfectly now.

Can delete/close this

Thanks in advance to anyone who can point anything out

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.