コード例 #1
0
ファイル: main.py プロジェクト: edart76/edPlugin
def testDdm():

    # test for skin
    mesh = cmds.polyCylinder(r=1, h=10, sx=8, sy=40, sz=8, ax=(0, 0, 1),
                             ch=0)[0]
    # skin cluster to transfer base weights
    skcMesh = cmds.duplicate(mesh, n="skcMesh")[0]
    refMesh = cmds.duplicate(mesh, n="refDdmMesh")[0]
    joints = []
    refJoints = []

    for i in range(3):
        jnt = cmds.createNode("joint", n="mainJnt_{}".format(i))
        cmds.setAttr(jnt + ".translateZ", i * 5 - 5)
        joints.append(jnt)
        if i: cmds.parent(jnt, joints[i - 1])

    skin = cmds.skinCluster(joints, skcMesh)[0]
    ddm = cmds.deformer(mesh, type="directDeltaMush")[0]
    refDdm = cmds.deformer(refMesh, type="refDDM")[0]

    for mush in [ddm, refDdm]:

        # copy matrix connections
        for i in range(3):
            cmds.connectAttr(joints[i] + ".worldMatrix[0]",
                             mush + ".matrix[{}]".format(i))
            #cmds.connectAttr(joints[i] + ".worldMatrix[0]", refDdm + ".matrix[{}]".format(i))
            pass

        # copy plug connections and weights to deltamush
        copyPlugs = ("weightList", "bindPreMatrix")

        size = cmds.getAttr(skin + ".weightList", size=1)
        cmds.setAttr(mush + ".weightList", size=size)

        cmds.select(cl=1)
        for i in copyPlugs:
            sourcePlug = getMPlug(getMObject(skin), i)
            sourceDH = om.MArrayDataHandle(sourcePlug.asMDataHandle())
            sinkPlug = getMPlug(getMObject(mush), i)
            sinkDH = om.MArrayDataHandle(sinkPlug.asMDataHandle())

            sinkDH.copy(sourceDH)

            sourceDH = sourcePlug.asMDataHandle()
            sinkPlug.setMDataHandle(om.MDataHandle(sourceDH))

            cmds.select(mush)

        # direct weight connections from skincluster to allow live weight editing
        for i in range(cmds.getAttr(skin + ".weightList", size=1)):
            array = skin + ".weightList[{}]".format(i)
            # for n in range( cmds.getAttr(array + ".weights", size=1 )):
            # 	srcPlug = array + ".weights[{}]".format(n)

            srcPlug = array
            dstPlug = srcPlug.replace(skin, mush)
            cmds.connectAttr(srcPlug, dstPlug, f=1)

        cmds.setAttr(ddm + ".iterations", 10)
        cmds.setAttr(ddm + ".alpha", 0.5)
        cmds.setAttr(ddm + ".smoothTranslation", 10.0)
        cmds.setAttr(ddm + ".smoothRotation", 10.0)

    # move skc mesh off to side
    group = cmds.group(skcMesh, n="skcOffsetGrp")
    cmds.setAttr(group + ".translateX", 5)

    group = cmds.group(refMesh, n="refOffsetGrp")
    cmds.setAttr(group + ".translateX", -5)
コード例 #2
0
    def compute(self, pPlug, pData):

        #only compute if output is in out array
        if (pPlug.parent() == generalIk.aOutRot):
            # descend into coordinated cycles
            # inputs
            solverDH = pData.inputValue(generalIk.aSolver)
            solver = solverDH.asInt()

            iterationsDH = pData.inputValue(generalIk.aMaxIter)
            maxIter = iterationsDH.asInt()

            toleranceDH = pData.inputValue(generalIk.aTolerance)
            tolerance = toleranceDH.asFloat()

            rootMat = om.MMatrix()
            rootMatDH = pData.inputValue(generalIk.aRootMat)
            rootMat = rootMatDH.asMatrix()

            # target
            targetMat = om.MMatrix()
            targetMatDH = pData.inputValue(generalIk.aTargetMat)
            targetMat = targetMatDH.asMatrix()

            endMat = om.MMatrix()
            endMatDH = pData.inputValue(generalIk.aEndMat)
            endMat = endMatDH.asMatrix()
            print "endMat at start is {}".format(endMat)

            # get everything in root space
            targetRSmat = targetMat.__mul__(rootMat.inverse())

            # get reference matrix array from tip to root
            # this lets us virtually rebuild the parent-child hierarchy
            inJntArrayDH = pData.inputArrayValue(generalIk.aJnts)
            inLength = inJntArrayDH.__len__()
            # DON'T FORGET our useful arrays are one entry shorter than we have
            chainArray = om.MMatrixArray()
            jntArray = om.MMatrixArray()

            jntWeights = om.MFloatArray()

            for i in range(inLength):
                inJntArrayDH.jumpToPhysicalElement(i)
                childCompDH = inJntArrayDH.inputValue()

                childMat = om.MMatrix()
                childMatDH = om.MDataHandle(
                    childCompDH.child(generalIk.aJntMat))
                #childUpMatDH = om.MDataHandle(childCompDH.child(generalIk.aJntUpMat))
                # not needed atm
                childMat = childMatDH.asMatrix()
                print "joint{}mat is {}".format(i, childMat)

                parentMat = om.MMatrix()
                if i != 0:
                    inJntArrayDH.jumpToPhysicalElement(i - 1)
                    parentCompDH = inJntArrayDH.inputValue()
                    parentMatDH = om.MDataHandle(
                        parentCompDH.child(generalIk.aJntMat))
                    parentMat = parentMatDH.asMatrix()
                else:
                    # only applies to last in loop (so first in joints)
                    parentMat = rootMat

                chainMat = childMat.__mul__(parentMat.inverse())
                chainArray.append(chainMat)
                #chainArray is every joint in the space of its parent
                #chainArray[i] = jntMat[i] x jntMat[i-1].inverse
                jntArray.append(childMat)
                #childArray is just the joint matrices

                childWeightDH = om.MDataHandle(
                    childCompDH.child(generalIk.aJntWeight))
                childWeight = childWeightDH.asFloat()
                print "childWeight is {}".format(childWeight)

                jntWeights.append(childWeight)

            print ""
            #from here applies only to ccd algorithm

            gap = 1.0
            iter = 0
            while (iter < maxIter) and (gap > tolerance):
                print "ITERATION {}".format(iter)
                print ""

                for i in range(inLength):

                    print "computing joint {} of {}".format(i, inLength)

                    # welcome to the bone zone

                    # reconstruct hierarchy with matrices from previous iteration
                    # currently target is known in rootspace, and end isn't known at all
                    # backwards to get target and forwards to get end, both in active joint space
                    #
                    #                  +(target)
                    #               .
                    #             .
                    #           O
                    #         /   \       X(end)
                    #       /       \   /
                    #     /           O
                    #   /
                    #(root)
                    # this works by getting vector from active joint to end, from active joint to target,
                    # then aligning one to the other. joints are assumed to have direct parent-child
                    # hierarchy, so all rotations are inherited rigidly

                    # ccd operates from tip to root - see reference for actual algorithm
                    jntMat = om.MMatrix()
                    jntMat = jntArray.__getitem__(inLength - (i + 1))
                    print "jntMat is {}".format(jntMat)
                    chainMult = om.MMatrix()

                    #backwards
                    for b in range(inLength - i):
                        #multiply targetRootSpaceMat by inverse chainMats,
                        #starting from ROOT
                        print "chainArray[b] is {}".format(chainArray[b])

                        if b == 0:
                            # at first joint, only equals root matrix
                            chainMult = chainArray[b].inverse()

                        else:
                            chainMult.__imul__(chainArray[b].inverse())

                        print "chainMult at {} is {}".format(b, chainMult)
                        print "endMat is {}".format(endMat)
                        print "endMat x chainMult is {}".format(
                            endMat.__mul__(chainMult))

                    #forwards
                    # only need end in joint space
                    endJSmat = endMat.__mul__(jntMat.inverse())
                    targetJSmat = targetRSmat * chainMult

                    # check gap is still important
                    gapVec = om.MVector(targetJSmat[12] - endJSmat[12],
                                        targetJSmat[13] - endJSmat[13],
                                        targetJSmat[14] - endJSmat[14])
                    gap = gapVec.length()
                    if gap > tolerance:

                        print "gap is {}".format(gap)
                        print "end JS is {}".format(endJSmat)
                        print "endMat v2 at {} is {}".format(i, endMat)
                        print "target JS is {}".format(targetJSmat)
                        targetJStrans = om.MTransformationMatrix(
                            targetJSmat).translation(1)
                        print "targetJStrans at {} is {}".format(
                            i, targetJStrans)

                        # we don't just want to aim each joint, we want to
                        # aim the end, by rotating each joint in turn

                        # first get the aim matrix from joint to end
                        endAimMat = om.MMatrix()
                        endAimMat = lookAt(jntMat, endJSmat)
                        print "endAimMat is {}".format(endAimMat)
                        #jntMat.__imul__(endAimMat)

                        # then from that, aim from end to target
                        targetAimMat = om.MMatrix()
                        targetAimMat = lookAt(jntMat, targetJSmat)

                        # is weighting this simple?
                        #print "jntWeight is {}".format(jntWeights.__getitem__(i))
                        targetAimMat.__imul__(jntWeights.__getitem__(i))
                        print "targetAimMat is {}".format(targetAimMat)

                        #constraints are going to be fun, but for now
                        jntMat.__imul__(targetAimMat)
                        endMat.__imul__(targetAimMat)

                        print "finalEndMat is {}".format(endMat)

                        #end of if block and aim procedure
                        print ""
                    else:
                        print ""
                        print "gap is within tolerance, ending"
                        break

                    jntArray.__setitem__(i, jntMat)
                    #end of single iteration along joint chain
                print ""

                iter = iter + 1

                #end of all iterations, computation has completed

            #convert jntArray of matrices to useful rotation values
            outArrayDH = pData.outputArrayValue(generalIk.aOutArray)

            targetRSTransA = om.MTransformationMatrix(targetRSmat).translation(
                4)
            print "target in RS world is {}".format(targetRSTransA)

            for i in range(0, inLength):
                outArrayDH.jumpToPhysicalElement(i)
                outCompDH = outArrayDH.outputValue()

                outRotDH = outCompDH.child(generalIk.aOutRot)
                outRxDH = outRotDH.child(generalIk.aOutRx)
                outRyDH = outRotDH.child(generalIk.aOutRy)
                outRzDH = outRotDH.child(generalIk.aOutRz)

                outRotVals = om.MTransformationMatrix(jntArray[i]).rotation()
                # unitConversions bring SHAME on family
                xAngle = om.MAngle(outRotVals[0])
                yAngle = om.MAngle(outRotVals[1])
                zAngle = om.MAngle(outRotVals[2])
                outRxDH.setMAngle(xAngle)
                outRyDH.setMAngle(yAngle)
                outRzDH.setMAngle(zAngle)

            outArrayDH.setAllClean()

            pData.setClean(pPlug)