MEL and Python code to restore joint positions to their bind pose based on skincluster's .bindPreMatrix
Go to bind pose that works even when bindPose node is corrupted - 04/2023 - #Jumble
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