Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I started by comparing my values to the ones I read from Assimp (an open source model loader). Stepping through the code I looked at where they built their bind matrices and their inverse bind matrices.</p> <p>Eventually I ended up in <code>SceneAnimator::GetBoneMatrices</code>, which contains the following:</p> <pre><code>// Bone matrices transform from mesh coordinates in bind pose to mesh coordinates in skinned pose // Therefore the formula is offsetMatrix * currentGlobalTransform * inverseCurrentMeshTransform for( size_t a = 0; a &lt; mesh-&gt;mNumBones; ++a) { const aiBone* bone = mesh-&gt;mBones[a]; const aiMatrix4x4&amp; currentGlobalTransform = GetGlobalTransform( mBoneNodesByName[ bone-&gt;mName.data ]); mTransforms[a] = globalInverseMeshTransform * currentGlobalTransform * bone-&gt;mOffsetMatrix; } </code></pre> <p><code>globalInverseMeshTransform</code> is always identity, because the mesh doesn't transform anything. <code>currentGlobalTransform</code> is the bind matrix, the joint's parent's local matrices concatenated with the joint's local matrix. And <code>mOffsetMatrix</code> is the inverse bind matrix, which comes directly from the skin.</p> <p>I checked the values of these matrices to my own (oh yes I compared them in a watch window) and they were exactly the same, off by maybe 0.0001% but that's insignificant. So why does Assimp's version work and mine doesn't even though the formula is the same?</p> <p>Here's what I got:</p> <p><img src="https://i.stack.imgur.com/deA1H.png" alt="Inversed!"></p> <p>When Assimp finally uploads the matrices to the skinning shader, they do the following:</p> <pre><code>helper-&gt;piEffect-&gt;SetMatrixTransposeArray( "gBoneMatrix", (D3DXMATRIX*)matrices, 60); </code></pre> <p>Waaaaait a second. They upload them <em>transposed</em>? It couldn't be that easy. No way.</p> <p><img src="https://i.stack.imgur.com/2orVs.png" alt="enter image description here"></p> <p>Yup.</p> <p>Something else I was doing wrong: I was converting the coordinates the right system (centimeters to meters) <em>before</em> applying the skinning matrices. That results in completely distorted models, because the matrices are designed for the original coordinate system.</p> <p><strong>FUTURE GOOGLERS</strong></p> <ul> <li>Read all the node transforms (rotate, translation, scale, etc.) in the order you receive them.</li> <li>Concatenate them to a joint's <strong>local matrix</strong>.</li> <li>Take the joint's parent and multiply it with the local matrix.</li> <li>Store that as the <strong>bind matrix</strong>.</li> <li>Read the skin information.</li> <li>Store the joint's <strong>inverse bind pose matrix</strong>.</li> <li>Store the joint <strong>weights</strong> for each vertex.</li> <li>Multiply the <strong>bind matrix</strong> with the <strong>inverse bind pose matrix</strong> and <strong>transpose it</strong>, call it the <strong>skinning matrix</strong>.</li> <li>Multiply the <strong>skinning matrix</strong> with the <strong>position</strong> times the joint <strong>weight</strong> and add it to the <strong>weighted position</strong>.</li> <li>Use the <strong>weighted position</strong> to render.</li> </ul> <p>Done!</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload