Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How can I get the original bone bind position ( and not the matrix)?

Discussion in 'Animation' started by 00christian00, Mar 22, 2020.

  1. 00christian00

    00christian00

    Joined:
    Jul 22, 2012
    Posts:
    1,035
    So I know I can access the matrix that that deform the vertices with Mesh.bindposes, but how can I do the inverse?
    I need to access the original position of each bone, as defined when I skinned the mesh in the 3D software.
    How do I calculate it? Is it possible?
     
    moji_mport likes this.
  2. 00christian00

    00christian00

    Joined:
    Jul 22, 2012
    Posts:
    1,035
    I found the code in the unity source code, Thanks guys.

    Code (CSharp):
    1. public static void GetBindPoseBonePositionRotation(Matrix4x4 skinMatrix, Matrix4x4 boneMatrix, Transform bone, out Vector3 position, out Quaternion rotation)
    2.     {
    3.         // Get global matrix for bone
    4.         Matrix4x4 bindMatrixGlobal = skinMatrix * boneMatrix.inverse;
    5.  
    6.         // Get local X, Y, Z, and position of matrix
    7.         Vector3 mX = new Vector3(bindMatrixGlobal.m00, bindMatrixGlobal.m10, bindMatrixGlobal.m20);
    8.         Vector3 mY = new Vector3(bindMatrixGlobal.m01, bindMatrixGlobal.m11, bindMatrixGlobal.m21);
    9.         Vector3 mZ = new Vector3(bindMatrixGlobal.m02, bindMatrixGlobal.m12, bindMatrixGlobal.m22);
    10.         Vector3 mP = new Vector3(bindMatrixGlobal.m03, bindMatrixGlobal.m13, bindMatrixGlobal.m23);
    11.  
    12.         // Set position
    13.         // Adjust scale of matrix to compensate for difference in binding scale and model scale
    14.         float bindScale = mZ.magnitude;
    15.         float modelScale = Mathf.Abs(bone.lossyScale.z);
    16.         position = mP * (modelScale / bindScale);
    17.  
    18.         // Set rotation
    19.         // Check if scaling is negative and handle accordingly
    20.         if (Vector3.Dot(Vector3.Cross(mX, mY), mZ) >= 0)
    21.             rotation = Quaternion.LookRotation(mZ, mY);
    22.         else
    23.             rotation = Quaternion.LookRotation(-mZ, -mY);
    24.     }
    Where skinMatrix is the skin transform localToWorldMatrix and boneMatrix is the bindpose.
    I needed to adapt a single face mesh to multiple body with different skeletons and I needed the bind position of the bones to compute where to locate the face mesh and alter its bind pose.

    Full code:
    https://github.com/Unity-Technologi...itor/Mono/Inspector/Avatar/AvatarSetupTool.cs
     
    hzn403, naelstrof and moji_mport like this.