MEL and Python code to restore joint positions to their bind pose based on skincluster's .bindPreMatrix

Sometimes the bindPose node of a skincluster gets corrupted, however, the attribute .bindPreMatrix of the skincluster should be enough to restore the world position of the joints. This MEL procedure reads off every .bindPreMatrix values of a skincluster, invert them, and set the world transformation of each corresponding joint in the skin cluster:

string $skinClusterName = "skinCluster25";
// get the list of joints connected to it
string $joints[] = `skinCluster -q -inf $skinClusterName`;
// loop through each joint
int $acc = 0;
for ($joint in $joints) {
    float $m[] = `getAttr ($skinClusterName+".bindPreMatrix["+$acc+"]")`;
    float $im[] = invertRowMajor($m);
    xform -worldSpace -matrix $im[0] $im[1] $im[2] $im[3] $im[4] $im[5] $im[6] $im[7] $im[8] $im[9] $im[10] $im[11] $im[12] $im[13] $im[14] $im[15] $joint;
    $acc = $acc + 1;
}

global proc float[] invertRowMajor(float $m[])
{
    float $invOut[17];
    // Extra element to indicate if the inversion failed or not:
    $invOut[16] = 1;
    
    float $inv[16];    
  
    $inv[ 0] =  $m[5] * $m[10] * $m[15] - $m[5] * $m[14] * $m[11] - $m[6] * $m[9] * $m[15] + $m[6] * $m[13] * $m[11] + $m[7] * $m[9] * $m[14] - $m[7] * $m[13] * $m[10];
    $inv[ 1] = -$m[1] * $m[10] * $m[15] + $m[1] * $m[14] * $m[11] + $m[2] * $m[9] * $m[15] - $m[2] * $m[13] * $m[11] - $m[3] * $m[9] * $m[14] + $m[3] * $m[13] * $m[10];
    $inv[ 2] =  $m[1] * $m[ 6] * $m[15] - $m[1] * $m[14] * $m[ 7] - $m[2] * $m[5] * $m[15] + $m[2] * $m[13] * $m[ 7] + $m[3] * $m[5] * $m[14] - $m[3] * $m[13] * $m[ 6];
    $inv[ 3] = -$m[1] * $m[ 6] * $m[11] + $m[1] * $m[10] * $m[ 7] + $m[2] * $m[5] * $m[11] - $m[2] * $m[ 9] * $m[ 7] - $m[3] * $m[5] * $m[10] + $m[3] * $m[ 9] * $m[ 6];
    $inv[ 4] = -$m[4] * $m[10] * $m[15] + $m[4] * $m[14] * $m[11] + $m[6] * $m[8] * $m[15] - $m[6] * $m[12] * $m[11] - $m[7] * $m[8] * $m[14] + $m[7] * $m[12] * $m[10];
    $inv[ 5] =  $m[0] * $m[10] * $m[15] - $m[0] * $m[14] * $m[11] - $m[2] * $m[8] * $m[15] + $m[2] * $m[12] * $m[11] + $m[3] * $m[8] * $m[14] - $m[3] * $m[12] * $m[10];
    $inv[ 6] = -$m[0] * $m[ 6] * $m[15] + $m[0] * $m[14] * $m[ 7] + $m[2] * $m[4] * $m[15] - $m[2] * $m[12] * $m[ 7] - $m[3] * $m[4] * $m[14] + $m[3] * $m[12] * $m[ 6];
    $inv[ 7] =  $m[0] * $m[ 6] * $m[11] - $m[0] * $m[10] * $m[ 7] - $m[2] * $m[4] * $m[11] + $m[2] * $m[ 8] * $m[ 7] + $m[3] * $m[4] * $m[10] - $m[3] * $m[ 8] * $m[ 6];
    $inv[ 8] =  $m[4] * $m[ 9] * $m[15] - $m[4] * $m[13] * $m[11] - $m[5] * $m[8] * $m[15] + $m[5] * $m[12] * $m[11] + $m[7] * $m[8] * $m[13] - $m[7] * $m[12] * $m[ 9];
    $inv[ 9] = -$m[0] * $m[ 9] * $m[15] + $m[0] * $m[13] * $m[11] + $m[1] * $m[8] * $m[15] - $m[1] * $m[12] * $m[11] - $m[3] * $m[8] * $m[13] + $m[3] * $m[12] * $m[ 9];
    $inv[10] =  $m[0] * $m[ 5] * $m[15] - $m[0] * $m[13] * $m[ 7] - $m[1] * $m[4] * $m[15] + $m[1] * $m[12] * $m[ 7] + $m[3] * $m[4] * $m[13] - $m[3] * $m[12] * $m[ 5];
    $inv[11] = -$m[0] * $m[ 5] * $m[11] + $m[0] * $m[ 9] * $m[ 7] + $m[1] * $m[4] * $m[11] - $m[1] * $m[ 8] * $m[ 7] - $m[3] * $m[4] * $m[ 9] + $m[3] * $m[ 8] * $m[ 5];
    $inv[12] = -$m[4] * $m[ 9] * $m[14] + $m[4] * $m[13] * $m[10] + $m[5] * $m[8] * $m[14] - $m[5] * $m[12] * $m[10] - $m[6] * $m[8] * $m[13] + $m[6] * $m[12] * $m[ 9];
    $inv[13] =  $m[0] * $m[ 9] * $m[14] - $m[0] * $m[13] * $m[10] - $m[1] * $m[8] * $m[14] + $m[1] * $m[12] * $m[10] + $m[2] * $m[8] * $m[13] - $m[2] * $m[12] * $m[ 9];
    $inv[14] = -$m[0] * $m[ 5] * $m[14] + $m[0] * $m[13] * $m[ 6] + $m[1] * $m[4] * $m[14] - $m[1] * $m[12] * $m[ 6] - $m[2] * $m[4] * $m[13] + $m[2] * $m[12] * $m[ 5];
    $inv[15] =  $m[0] * $m[ 5] * $m[10] - $m[0] * $m[ 9] * $m[ 6] - $m[1] * $m[4] * $m[10] + $m[1] * $m[ 8] * $m[ 6] + $m[2] * $m[4] * $m[ 9] - $m[2] * $m[ 8] * $m[ 5];
  
    float $det = $m[0] * $inv[0] + $m[4] * $inv[1] + $m[8] * $inv[2] + $m[12] * $inv[3];
  
    if($det == 0){
        $invOut[16] = -1;
        return $invOut;
    }
  
    $det = 1.0 / $det;
  
    for($i = 0; $i < 16; $i++)
        $invOut[ $i ] = $inv[ $i ] * $det;
  
    return $invOut;
}


Python

    
from maya.api.OpenMaya import MMatrix
from typing import List
    
def floatToMatrix(floatList : List[float]) -> MMatrix:
    # convert list of 16 floats to an OpenMaya MMatrix    
    matrix = MMatrix()
    for i in range(16):
        matrix[i] = floatList[i]
    return matrix

def matrixToFloatList(matrix : MMatrix) -> List[float] :
    # converts MMatrix to a list of 16 floats    
    return [matrix[i] for i in range(16)]
    
    
def restoreBindPose(skinClusterName : str):
    # string $joints[] = `skinCluster -q -inf $skinClusterName`;
    infjnts : List[str] = cmds.skinCluster(skinClusterName, q=True, influence=True)

    for i, joint in enumerate(infjnts):
        prebindMatrix : List[float] = cmds.getAttr("%s.bindPreMatrix[%s]" % (skinClusterName, i))
        matrixVals = matrixToFloatList(floatToMatrix(prebindMatrix).inverse())
        cmds.xform(joint, worldSpace=True, matrix=matrixVals)

No comments

(optional field, I won't disclose or spam but it's necessary to notify you if I respond to your comment)
All html tags except <b> and <i> will be removed from your comment. You can make links by just typing the url or mail-address.
Anti-spam question: