[SOLVED] MGSkinmeshPipeline Root Rotation Animation Problem

Usually works ok but some animations seem to cause a problem. I’m wondering if anyone has any ideas what might be causing the root to rotate in unexpected ways. (Animation works properly in other FBX viewers)
I’m under the impression that it has something to do with the root and some transforms that are being applied wrong or maybe there’s something else going on?
(The root should only rotate left and right by a tiny amount but there’s some extra rotation added to X-axis rotation somehow):

Any ideas as to anything that might cause this?

Even if I remove all animation from the rootbone, this extra animation persists and I can’t see anywhere that it could be coming from. :confused:

Can you set the x rotation to -90 in the pipeline tool ?
Not sure that will actually fix it.

Thanks for reply - Don’t actually need to fix the model orientation - the other animations with the same model work.
I found out that if I turn off animation keys for the foot controllers, everything works as it should. Weird thing is if I try it with everything turned on - same file in your animation engine - everything works perfectly. (O__O) So weird… So that must mean your animator does something different with the data than the original MG one. I’m gonna see if I can narrow it down to a specific bone.
My hunch is that one of the leg bones connected to the root is also rotating the root bone in the MG version.

Ya i seem to remember having this problem early on and i squashed it but i can’t remember exactly the what and why cause of it.

Yup. I vaguely recall ppl mentioning it before.

With more testing - I think I found the root of the problem - - I’m very sure it’s using rotations from the right thigh bone on the root (left side if looking at front of character).

I’ll have to modify the pipeline processor thingy to find the true root bone. I tried adding the test that nkast used but it’s still using the wrong one. I’ll have to figure out how it actually works and see if I can convince it to use the actual root. XD
If it IS using the correct root, then somehow it’s inheriting transforms meant for the thigh on the root. :open_mouth:

Looks like it’s using the correct root BUT the first child (R_Thigh) is being applied to the entire skeleton (as though it was a root). Well… I guess I better fix that… XD

Well i’ve got mine all taken apart as i put it back together for the first round of refactoring it adding the changes i made broke a lot of minor stuff and some new stuff i added like individual mesh draws ect…

Oh man, that’s no fun. That reminds me - I seen you had something where you could make a dummy for the flat list and it just gave me the idea of adding a dummy bone to my character to bump the hierarchy so even if the second bone is the one acting as the root, it’ll be ok cuz it’ll be the actual root anyway.
Well hopefully you get it working again.

My idea didn’t work - it just made things worse. I think by adding a bone and parenting the original root to it to make it the new root; it messes up the entire export. I think there are dependency transform chains that don’t integrate before exporting to FBX. I guess once a root is established - one can never mess with it after if you want it to export correctly. ;p

I do that for a different reason though.

The dummy bone really defaults to the mesh node.
Some specific animations for example blender will output mesh animations as node animations with no bones, assimp doesn’t see them as mesh animations either, so that’s kind of a problem.

model = modelReader.LoadAsset("AnimatedCube5.fbx");
^^ Is a cube model i made to test for those kinds of node animations.

So i basically make a dummy node to handle it and that entails re-indexing bones so that all the vertice id’s for a mesh with no bones default to id 0 and with a weight of 1 then that automatically points to the dummy node which normally is now set to identity.

When the node animation exists it runs thru its chain and sets that matrix for bone 0 i treat nodes that have mesh names as or indexs to meshes as if they are bone 0, then later draw pushes the bone matrix to the gpu and it blends the vertices with the transform for that bone.

Right now im doing it for each mesh and pushing the bones per mesh to the gpu instead of how i was doing it before with a flat bone list per model. I also now rename the mesh node in the tree to replace the dummybone name with the mesh node name and make a bone with a offset of identity that is linked to the node which is also linked to the mesh and animation node.

I can send you the current version but its still pretty busted up including some of the new methods.

2 Likes

Now I get it.
Righton. I’ll probably use your animation engine in most of my own 3d projects. :wink:

I was trying to make a short simple tutorial to make complex animations to work with regular skinned-mesh example. If only I could figure out one last thing.

I noticed something weird and impossible (or at least I thought at first).

I double-checked the hierarchy of the bones and transforms and they’re actually correct. So there’s no possible way that the R_Thigh could be effecting the rotation of the root or other bones… even though it does… and then I realized it’s possible that somehow every single vertex(by weighted bones) in the model is receiving transformation from the R_Thigh. (Bone 1 instead of Bone 0) - I just can’t seem to pinpoint where in any code that this is happening.

Anyway, I believe there’s a bug in the external code which can not be noticed most of the time because usually bone 1 is the lower-spine bone which usually doesn’t do anything anyway – and so the bug usually slips by unnoticed.

I mean it would be great if monogame handled everything, but when i tried to use it i had similar problems and some others.

Besides that i wanted full control over the model the loader and the shaders.

Yah for sure - realistically it’s the best way to go. More control is better.

Update:

  1. I know if I play with the Right_Thigh data, the entire character follows whatever it does.
  2. I know the hierarchy and world transforms are being built perfectly
  3. If I prevent anything from using the Right_Thigh as a parent - IT STILL rotates the entire skeleton by it
  4. The Root transform does NOT contain transformation influence from R_Thigh

How is this even possible? :thinking:

Shouldn’t be possible

On mine the right thigh is off the root bone in its own transform route ending at the right toe.

Logically either the Right thigh is transforming the root node somehow or the heirarchy is in fact not built correctly i suppose that would be the same thing. Can you print out the transform heirarchy ?

On the original model the one that didn’t work at first this is the transform tree for the thigh minus the scene root node before it, i didn’t want to drag everything in.

  Root_$AssimpFbx$_Translation
  |_children.Count: 1 |_parent: RootNode
  |_hasARealBone: False
  |_isThisAMeshNode: False


    Root_$AssimpFbx$_PreRotation
    |_children.Count: 1 |_parent: Root_$AssimpFbx$_Translation
    |_hasARealBone: False
    |_isThisAMeshNode: False


      Root_$AssimpFbx$_Rotation
      |_children.Count: 1 |_parent: Root_$AssimpFbx$_PreRotation
      |_hasARealBone: False
      |_isThisAMeshNode: False


        Root_$AssimpFbx$_Scaling
        |_children.Count: 1 |_parent: Root_$AssimpFbx$_Rotation
        |_hasARealBone: False
        |_isThisAMeshNode: False


          Root
          |_children.Count: 5 |_parent: Root_$AssimpFbx$_Scaling
          |_hasARealBone: True
          |_isThisAMeshNode: False
          |_uniqueMeshBones.Count: 1
          |_node: Root  lists  uniqueMeshBone[0] ...  meshIndex: 0  meshBoneIndex: 2   mesh[0]bone[2].Name: Root  in  mesh[0].Name: Body


            R_Thigh
            |_children.Count: 1 |_parent: Root
            |_hasARealBone: True
            |_isThisAMeshNode: False
            |_uniqueMeshBones.Count: 1
            |_node: R_Thigh  lists  uniqueMeshBone[0] ...  meshIndex: 0  meshBoneIndex: 3   mesh[0]bone[3].Name: R_Thigh  in  mesh[0].Name: Body
            |^has corresponding Animation[0].Node[80].Name: R_Thigh  positionKeyCount: 200  rotationKeyCount: 200  scaleKeyCount: 200

Maybe the root bone is being removed and then the right thigh is taking its spot but that would be pretty hard to isolate and fix without debug info.

Yah, it seemed like it might be replacing bone 1 (R_Thigh) as the root or somehow applying the rotation to both the root and the thigh itself.
Here’s the data being processed in AnimationPlayer as it builds the WorldTransforms using this:

worldTransforms[0] = boneTransforms[0] * rootTransform; // Root bone.    
for (int bn = 1; bn < worldTransforms.Length; bn++) {       // 0 is processed differently 
    int parentBone = skinningDataValue.SkeletonHierarchy[bn];                    
    worldTransforms[bn] = boneTransforms[bn] * worldTransforms[parentBone];                
}

pelvis parent: RootNode
spine1 parent: pelvis
spine2 parent: spine1
head parent: spine2
R_ear1 parent: head
R_ear2 parent: R_ear1
L_ear1 parent: head
L_ear2 parent: L_ear1
R_Clav parent: spine2
R_bicep parent: R_Clav
R_forearm parent: R_bicep
L_Clav parent: spine2
L_bicep parent: L_Clav
L_forearm parent: L_bicep
tail parent: spine1
L_Thigh parent: pelvis
L_Calf parent: L_Thigh
L_Foot parent: L_Calf
R_Thigh parent: pelvis
R_Calf parent: R_Thigh
R_Foot parent: R_Calf

bone: 0
worldTransform[0]: {M11:0.006566166 M12:-0.9695151 M13:0.2449432 M14:0} {M21:0.07569481 M22:0.2447276 M23:0.9666326 M24:0} {M31:-0.9971094 M32:0.0121938 M33:0.07499421 M34:0} {M41:0 M42:22.98113 M43:-2.263824 M44:1}

bone: 1 parentBone = 0
worldTransform[1]: {M11:0.03787259 M12:-0.7570251 M13:0.652287 M14:0} {M21:0.05752876 M22:0.6533244 M23:0.7548891 M24:0} {M31:-0.9976252 M32:0.008935602 M33:0.06829384 M34:0} {M41:-5.870191 M42:21.26965 M43:-1.051334 M44:1}

bone: 2 parentBone = 1
worldTransform[2]: {M11:-0.01745005 M12:-0.9919887 M13:-0.1251143 M14:0} {M21:0.06662873 M22:-0.1260089 M23:0.989789 M24:0} {M31:-0.9976252 M32:0.008935602 M33:0.06829384 M34:0} {M41:-5.493477 M42:13.73964 M43:5.436862 M44:1}

bone: 3 parentBone = 2
worldTransform[3]: {M11:0.07121501 M12:-0.07789755 M13:0.9944146 M14:0} {M21:0.005567377 M22:0.9969612 M23:0.07769832 M24:0} {M31:-0.9974455 M32:2.935529E-06 M33:0.07143231 M34:0} {M41:-5.645341 M42:5.105449 M43:4.34816 M44:1}

bone: 4 parentBone = 3
worldTransform[4]: {M11:0.07029467 M12:0.1423636 M13:0.9873152 M14:0} {M21:-0.01018734 M22:0.9898143 M23:-0.1419987 M24:0} {M31:-0.9974743 M32:-7.642402E-05 M33:0.07102901 M34:0} {M41:-5.053619 M42:4.4582 M43:12.6107 M44:1}

bone: 5 parentBone = 4
worldTransform[5]: {M11:0.07029469 M12:0.1423636 M13:0.9873152 M14:0} {M21:-0.01018687 M22:0.9898143 M23:-0.1419988 M24:0} {M31:-0.9974743 M32:-7.595164E-05 M33:0.07102896 M34:0} {M41:-4.716876 M42:5.140189 M43:17.3404 M44:1}

bone: 6 parentBone = 0
worldTransform[6]: {M11:-0.006464589 M12:-0.9737733 M13:-0.2274282 M14:0} {M21:-0.01372441 M22:0.2274978 M23:-0.973682 M24:0} {M31:0.999885 M32:-0.003173077 M33:-0.01483516 M34:0} {M41:5.941849 M42:21.12519 M43:-1.939743 M44:1}

bone: 7 parentBone = 6
worldTransform[7]: {M11:-0.01517001 M12:-0.1990635 M13:-0.9798694 M14:0} {M21:0.0001561213 M22:0.9799814 M23:-0.1990888 M24:0} {M31:0.999885 M32:-0.003173096 M33:-0.01483526 M34:0} {M41:5.877546 M42:11.43922 M43:-4.201939 M44:1}

bone: 8 parentBone = 7
worldTransform[8]: {M11:0.006268287 M12:-0.8378724 M13:0.5458302 M14:0} {M21:-0.01007776 M22:-0.5458659 M23:-0.8378121 M24:0} {M31:0.9999295 M32:-0.0002490378 M33:-0.01186553 M34:0} {M41:5.745509 M42:9.706318 M43:-12.73054 M44:1}

bone: 9 parentBone = 8
worldTransform[9]: {M11:0.01221573 M12:-0.1130201 M13:0.9935178 M14:0} {M21:-0.001458018 M22:-0.9935925 M23:-0.1130108 M24:0} {M31:0.9999242 M32:-6.799759E-05 M33:-0.01230226 M34:0} {M41:5.797591 M42:2.744477 M43:-8.195272 M44:1}

bone: 10 parentBone = 9
worldTransform[10]: {M11:0.01221573 M12:-0.1130201 M13:0.9935176 M14:0} {M21:-0.001458018 M22:-0.9935924 M23:-0.1130108 M24:0} {M31:0.9999242 M32:-6.799759E-05 M33:-0.01230226 M34:0} {M41:5.856111 M42:2.203058 M43:-3.435853 M44:1}

bone: 11 parentBone = 0
worldTransform[11]: {M11:3.222376E-07 M12:0.9912365 M13:0.1320997 M14:0} {M21:-0.03787695 M22:0.1320049 M23:-0.9905251 M24:0} {M31:-0.9992824 M32:-0.005003273 M33:0.03754507 M34:0} {M41:1.804705E-08 M42:22.98113 M43:-2.263824 M44:1}

bone: 12 parentBone = 11
worldTransform[12]: {M11:-0.006373205 M12:0.999171 M13:0.04020571 M14:0} {M21:0.01645217 M22:0.04030579 M23:-0.9990519 M24:0} {M31:-0.9998444 M32:-0.005705754 M33:-0.0166954 M34:0} {M41:8.776871E-07 M42:27.00257 M43:-1.727898 M44:1}

ETC…

What I find really weird, is if I make all the bones ignore bone1 as a parent and instead use bone 0, it still rotates the model by bone1’s transform. So one would think that bone 0 is the culprit and has the bone1 transform in it already - but if I simply tell it to stop rotating bone 1 – magically the model stops rotating even though nothing’s parented to it…
This makes me think there’s an index lookup somewhere that’s high on crack. XD

It’s really hard to tell whats going on to be honest i been looking at it for some time now.
It really does look like a index is messed up or the transforms have been condensed to nodes with bones improperly.

Have you tried other models like the dude fbx to see if that works?

Hey, good idea!
Yah, I just tried it and he’s doing the same thing - parented to the right thigh bone… so now I’m thinking maybe there’s something I did to the processor myself without realizing it - or something in my custom shader that’s causing it to apply bone 1 to everything – because I don’t remember it doing this before with TheDude.
Aha! It’s a great clue at least! XD