title: Bones rotate around parent - OpenGL Animation/Skinning
body: <p>I am having an issue with my bone skinning where instead of my bones rotating around their local origin, they instead rotate around the their parent. <a href="https://i.stack.imgur.com/GcWt5.png" rel="nofollow noreferrer">Left - my engine. Right - blender</a></p>
  <p>There are two locations in the pipeline that I suspect are at fault, but I cant tell where exactly it is. First, I have this bit of code that actually calculates the bone matrices:</p>
  <pre><code>void CalculateBoneTransform(DSkeletonBone sb, dmat4x4f parentTransform, std::vector&lt;DSkeletonBone&gt; boneOverrides)
  {
      if (boneDataIndex.count(sb.name) == 0) return;
  
      Transform transform = sb.localTransform;
      for (auto&amp; bo : boneOverrides)
      {
          if (bo.name == sb.name)
          {
              transform = bo.localTransform;
          }
      }
  
      dmat4x4f globalTransform = dmat4x4f::Mul(parentTransform, transform.GetMatrix());
  
      dmat4x4f finalTransform = dmat4x4f::Mul(globalTransform, sb.inverseTransform);
  
      finalTransforms[boneDataIndex[sb.name]] = finalTransform;
  
      for (auto&amp; pbC : sb.children)
      {
          CalculateBoneTransform(pbC, globalTransform, boneOverrides);
      }
  }
  </code></pre>
  <p>The boneOverrides come from anything that would like to override a bone (such as an animation).
  finalTransforms is the array that is pushed to the shader.</p>
  <p>In my mesh/anim parser, I have this code that calculates the inverse bind pose matrices (using OpenFBX, but this is not relevant):</p>
  <pre><code>            glm::mat4 local = glm::inverse(GetMatFromVecs(
                  boneData[skin-&gt;getCluster(i)-&gt;name].pos,
                  boneData[skin-&gt;getCluster(i)-&gt;name].rot,
                  boneData[skin-&gt;getCluster(i)-&gt;name].scl));
  
              for (Object* parent = skin-&gt;getCluster(i)-&gt;getLink()-&gt;getParent(); parent != NULL; parent = parent-&gt;getParent())
              {
                  glm::mat4 parentInverseTransform = glm::inverse(GetMatFromVecs(
                      parent-&gt;getLocalTranslation(),
                      parent-&gt;getLocalRotation(),
                      parent-&gt;getLocalScaling()));
  
                  local = parentInverseTransform * local;
              }
              boneData[skin-&gt;getCluster(i)-&gt;name].offset = local;
  </code></pre>
  <p>The getLocalXX functions get the item in local space.</p>
  <p>And the GetMatFromVecs function referenced above:</p>
  <pre><code>    glm::mat4 GetMatFromVecs(Vec3 pos, Vec3 rot)
      {
          glm::mat4 m(1);
          m = glm::scale(m, glm::vec3(1,1,1));
          m = glm::rotate(m, (float)rot.x * 0.0174532925f, glm::vec3(1, 0, 0));
          m = glm::rotate(m, (float)rot.y * 0.0174532925f, glm::vec3(0, 1, 0));
          m = glm::rotate(m, (float)rot.z * 0.0174532925f, glm::vec3(0, 0, 1));
          m = glm::translate(m, glm::vec3(pos.x, pos.y, pos.z));
          return m;
      }
  </code></pre>
  <p>Notice I am rotating first, then translating (this is also the case with the GetMatrix() function referenced in the first snippit, by the way).</p>
  <p>So my question is, why is this happening? Also, what are some causes of this type of thing in mesh skinning? My translations are local, but rotations are not.</p>