SkinnedEffect reading incorrect bone scales (scale drifting?)


I’ve been working on my game for about a year. It makes very heavy use of animated skinned models. I’ve been using BetterSkinned for my animations, and its been working very well, but… it has no implementation for scaling bones. I tried to implement this myself, and have been getting very warped meshes, so I did some debugging.

For this, I used an animation which was just my model in its resting position (translation, rotation and scale of all bones being the default).

Now, in the AnimationClipReader class, I got it to spit out the information of the keyframes as it read them, knowing that it should say the scale for every bone is [1,1,1] (because that’s the scale of every bone in Blender).

However, when I looked at my output (which I’ve abbreviated below), I saw the following (I refer to the S values, which are the scale of each bone at that keyframe):

-- T: [0,0,0]
-- R: [0,0,0,1]
-- S: [1,1,1]
-- U: [1,1,1]

-- T: [0,0,0]
-- R: [0,0,0,1]
-- S: [1,1,1]
-- U: [1,1,1]

-- T: [0,0,0]
-- R: [-9.95,0,0,5.025]
-- S: [100,0,0] <---------
-- U: [100,0,0]

-- T: [0,0,0]
-- R: [0.707,0,0,0.707]
-- S: [1,0,0] <---------
-- U: [1,-2,-2]

-- T: [0.086,0.913,-0.049]
-- R: [0.731,0.229,0.642,0.023]
-- S: [0.07,-0.894,-0.174] <---------
-- U: [1,1,1]

-- T: [0,0.382,0]
-- R: [0.094,-0.48,0.437,0.755]
-- S: [0.157,0.601,0.521] <---------
-- U: [1,1,1]

The scale for each bone was not [1,1,1]!

Then, I discovered that the rotation (R value) of each bone for some reason influenced the value that the Scale (S value) would have. As in, if I changed the rotation of a bone, but left its scale as [1,1,1] in Blender, when I imported it the S value would still change.

So, I added the following code to modify the scale based on the bones rotation:

Matrix test = Matrix.CreateScale(keyframe.Scale) / Matrix.CreateFromQuaternion(keyframe.Rotation);
keyframe.Scale = test.Scale;

This resulted in the U values in my output (notice that most are the [1,1,1] I was expecting).

However, even with this fix, some bones (like the root) are still not being imported with the correct scaling. I’m afraid I don’t know that much about how bone transforms worked (hence relying on a third-party library), so I’m wondering if anyone can explain what’s going on here? Why is my armature being imported with a scale of [100,0,0]?

Many thanks in advance!