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