Home Youtube GitHub

Matrix Constraint


#1

Hi there!
Wonder what do you think about matrix based constraints. Do you use a setup like this? In a few scripts that I’m working on, I use parent constraints, as I saw you’re using in mGear also right?
Just for tests, I’m trying to get a nice function to create/replace parent constraints and the results seem promising. Still, I have some issues but hope that’s just my bad - mainly with weighting the results are not the same as parent constraint.

I saw that practice on the cult of rig podcast, and on this blog is nicely described:


All best,
Krzysztof


#2

@Krzym

All the joints connection and many other parts are using this kind of connections in mGear. Is kind of the default way to go in mGear

Here is one function from rigbits for reference

def addJnt(obj=False,
           parent=False,
           noReplace=False,
           grp=None,
           jntName=None,
           *args):
    """Create one joint for each selected object.

    Args:
        obj (bool or dagNode, optional): The object to drive the new
            joint. If False will use the current selection.
        parent (bool or dagNode, optional): The parent for the joint.
            If False will try to parent to jnt_org. If jnt_org doesn't
            exist will parent the joint under the obj
        noReplace (bool, optional): If True will add the extension
            "_jnt" to the new joint name
        grp (pyNode or None, optional): The set to add the new joint.
            If none will use "rig_deformers_grp"
        *args: Maya's dummy

    Returns:
        pyNode: The New created joint.

    """
    if not obj:
        oSel = pm.selected()
    else:
        oSel = [obj]

    for obj in oSel:
        if not parent:
            try:
                oParent = pm.PyNode("jnt_org")
            except TypeError:
                oParent = obj
        else:
            oParent = parent
        if not jntName:
            if noReplace:
                jntName = "_".join(obj.name().split("_")) + "_jnt"
            else:
                jntName = "_".join(obj.name().split("_")[:-1]) + "_jnt"
        jnt = pm.createNode("joint", n=jntName)

        if grp:
            grp.add(jnt)
        else:
            try:
                defSet = pm.PyNode("rig_deformers_grp")
                pm.sets(defSet, add=jnt)
            except TypeError:
                pm.sets(n="rig_deformers_grp")
                defSet = pm.PyNode("rig_deformers_grp")
                pm.sets(defSet, add=jnt)

        oParent.addChild(jnt)

        jnt.setAttr("jointOrient", 0, 0, 0)
        try:
            mulmat_node = node.createMultMatrixNode(
                obj + ".worldMatrix", jnt + ".parentInverseMatrix")
            dm_node = node.createDecomposeMatrixNode(
                mulmat_node + ".matrixSum")
            pm.connectAttr(dm_node + ".outputTranslate", jnt + ".t")
            pm.connectAttr(dm_node + ".outputRotate", jnt + ".r")
            pm.connectAttr(dm_node + ".outputScale", jnt + ".s")
        except RuntimeError:
            for axis in ["tx", "ty", "tz", "rx", "ry", "rz"]:
                jnt.attr(axis).set(0.0)

    return jnt

#3

Oh, I see! Thank you, that’s how my journey with mgear looks like :wink: Each time I wrote something, it’s already inside - ofc. that a good thing :wink:

I wonder, why do you create MultMatrixNode first and then create DocomposeMatrix and connect the outputs, instead of just using MultMatrixNode function, which already has that functionality?

Do you have any other function that creates ‘parent’ with maintain offset?
How do you blend those parents? With node.createBlendNode or you’re using ‘wtAddMatrix’ node?
How about math nodes? I see it’s provided with mgear, but not sure if it’s used or not.


#4

As far I know, mulMatrix node doesn’t have a decomposed Matrix output. (not the default Maya node and not the mgear custom node)

the add joint function under shifter components has something like that. But there is nothing in the mgear core

I don’t use multiple parents

I am not using the math nodes (at less not yet :wink: )


#5

Thanks, good to know

About decompose matrix,I mean node.createMultMatrixNode(), which have target and transform attributes.

def createMultMatrixNode(mA, mB, target=False, transform='srt'):
    """Create Maya multiply Matrix node.

    Note:
        This node have same functionality as the default Maya matrix
        multiplication

    Arguments:
        mA (matrix): input matrix A.
        mB (matrix): input matrix B.
        target (dagNode): object target to apply the transformation
        transform (str): if target is True. out transform  to SRT valid
            value s r t

    Returns:
        pyNode: Newly created mGear_multMatrix node

    """
    node = pm.createNode("multMatrix")
    for m, mi in zip([mA, mB], ['matrixIn[0]', 'matrixIn[1]']):
        if isinstance(m, datatypes.Matrix):
            pm.setAttr(node.attr(mi), m)
        else:
            pm.connectAttr(m, node.attr(mi))
    if target:
        dm_node = pm.createNode("decomposeMatrix")
        pm.connectAttr(node + ".matrixSum",
                       dm_node + ".inputMatrix")
        if 't' in transform:
            pm.connectAttr(dm_node + ".outputTranslate",
                           target.attr("translate"), f=True)
        if 'r' in transform:
            pm.connectAttr(dm_node + ".outputRotate",
                           target.attr("rotate"), f=True)
        if 's' in transform:
            pm.connectAttr(dm_node + ".outputScale",
                           target.attr("scale"), f=True)

    return node

#6

Oh sorry I didn’t understood your question
node.createMultMatrixNode() connect the to the target SRT, because is the most used case. If I need to pipe other matrix, I just simple don’t set the target argument