def compute(self, plug, dataBlock): """ Node computation method: * plug is a connection point related to one of our node attributes (either an input or an output). * dataBlock contains the data on which we will base our computations. """ # pylint: disable=no-self-use if (plug != EulerScalarMath.outEuler and plug != EulerScalarMath.outEulerX and plug != EulerScalarMath.outEulerY and plug != EulerScalarMath.outEulerZ): return om2.kUnknownParameter operation = dataBlock.inputValue(EulerScalarMath.inOperation).asShort() euler = dataBlock.inputValue(EulerScalarMath.inEuler).asDouble3() scalar = dataBlock.inputValue(EulerScalarMath.inScalar).asDouble() eulerRotOder = dataBlock.inputValue( EulerScalarMath.inEulerRotOrder).asShort() outRotOrder = dataBlock.inputValue( EulerScalarMath.inResRotOrder).asShort() eEuler = om2.MEulerRotation(euler, eulerRotOder) outEulerHandle = dataBlock.outputValue(EulerScalarMath.outEuler) if operation == 0: eEuler.reorderIt(outRotOrder) outEulerHandle.set3Double(eEuler.x, eEuler.y, eEuler.z) elif operation == 1: eEuler.reorderIt(outRotOrder) eScalar = om2.MEulerRotation( om2.MAngle(scalar, om2.MAngle.kDegrees).asRadians(), om2.MAngle(scalar, om2.MAngle.kDegrees).asRadians(), om2.MAngle(scalar, om2.MAngle.kDegrees).asRadians(), outRotOrder) eOutEuler = eEuler + eScalar outEulerHandle.set3Double(eOutEuler.x, eOutEuler.y, eOutEuler.z) elif operation == 2: eEuler.reorderIt(outRotOrder) eScalar = om2.MEulerRotation( om2.MAngle(scalar, om2.MAngle.kDegrees).asRadians(), om2.MAngle(scalar, om2.MAngle.kDegrees).asRadians(), om2.MAngle(scalar, om2.MAngle.kDegrees).asRadians(), outRotOrder) eOutEuler = eEuler - eScalar outEulerHandle.set3Double(eOutEuler.x, eOutEuler.y, eOutEuler.z) elif operation == 3: eEuler.reorderIt(outRotOrder) eOutEuler = eEuler * scalar outEulerHandle.set3Double(eOutEuler.x, eOutEuler.y, eOutEuler.z) outEulerHandle.setClean()
def compute(self, plug, dataBlock): """ Node computation method: * plug is a connection point related to one of our node attributes (either an input or an output). * dataBlock contains the data on which we will base our computations. """ # pylint: disable=no-self-use if (plug != EulerMath.outEuler and plug != EulerMath.outEulerX and plug != EulerMath.outEulerY and plug != EulerMath.outEulerZ): return om2.kUnknownParameter operation = dataBlock.inputValue(EulerMath.inOperation).asShort() euler1 = dataBlock.inputValue(EulerMath.inEuler1).asDouble3() euler2 = dataBlock.inputValue(EulerMath.inEuler2).asDouble3() euler1RotOrder = dataBlock.inputValue( EulerMath.inEuler1RotOrder).asShort() euler2RotOrder = dataBlock.inputValue( EulerMath.inEuler2RotOrder).asShort() outRotOrder = dataBlock.inputValue(EulerMath.inResRotOrder).asShort() eEuler1 = om2.MEulerRotation(euler1, euler1RotOrder) eEuler2 = om2.MEulerRotation(euler2, euler2RotOrder) outEulerHdle = dataBlock.outputValue(EulerMath.outEuler) if operation == 0: eEuler1.reorderIt(outRotOrder) outEulerHdle.set3Double(eEuler1.x, eEuler1.y, eEuler1.z) elif operation == 1: eEuler1.reorderIt(outRotOrder) eEuler2.reorderIt(outRotOrder) eOutEuler = eEuler1 + eEuler2 outEulerHdle.set3Double(eOutEuler.x, eOutEuler.y, eOutEuler.z) elif operation == 2: eEuler1.reorderIt(outRotOrder) eEuler2.reorderIt(outRotOrder) eOutEuler = eEuler1 - eEuler2 outEulerHdle.set3Double(eOutEuler.x, eOutEuler.y, eOutEuler.z) elif operation == 3: eEuler1.reorderIt(outRotOrder) eEuler2.reorderIt(outRotOrder) eOutEuler = eEuler1 * eEuler2 outEulerHdle.set3Double(eOutEuler.x, eOutEuler.y, eOutEuler.z) outEulerHdle.setClean()
def compute(self, plug, dataBlock): """ Node computation method: * plug is a connection point related to one of our node attributes (either an input or an output). * dataBlock contains the data on which we will base our computations. """ # pylint: disable=no-self-use vector = dataBlock.inputValue(VectorToEuler.inVector).asFloat3() vVector = om2.MVector([unit * (math.pi / 180.0) for unit in vector]) eEuler = om2.MEulerRotation(vVector) outEulerHandle = dataBlock.outputValue(VectorToEuler.outEuler) outEulerHandle.set3Double(eEuler.x, eEuler.y, eEuler.z) outEulerHandle.setClean()
def getMRotFromNodeOutput(node_mob, rotOrder=om2.MEulerRotation.kXYZ): """ finds the angular output of the argument node and returns it as a Euler rotation where that angle is the X element :param node_mob: [MObject] the node to get the output port from :param rotOrder: [int] the factory constant for the desired rotation order the returned Euler rotation should be set to :return: [MEulerRotation] the Euler rotation composition where the angular output on the argument node is the X value """ mfn_dep = om2.MFnDependencyNode(node_mob) angle = om2.MAngle(0.0) if node_mob.hasFn(om2.MFn.kAnimBlend) and mfn_dep.hasAttribute( _MAYA_OUTPUT_ATTRIBUTE_NAME): plug = mfn_dep.findPlug(_MAYA_OUTPUT_ATTRIBUTE_NAME, False) angle = plug.asMAngle() rot = om2.MEulerRotation(angle.asRadians(), 0.0, 0.0, rotOrder) return rot
def compute(self, plug, dataBlock): """ Node computation method: * plug is a connection point related to one of our node attributes (either an input or an output). * dataBlock contains the data on which we will base our computations. """ rotation = dataBlock.inputValue(TwistExtractor.inRotation).asDouble3() rotOrder = dataBlock.inputValue( TwistExtractor.inRotationOrder).asShort() eRoll = om2.MEulerRotation(rotation, rotOrder) useUpObj = dataBlock.inputValue(TwistExtractor.inUseUpVec).asBool() revTwist = dataBlock.inputValue(TwistExtractor.inInvTwist).asBool() # Non flip ROO = XYZ # Not working = XZY twistOrder = om2.MEulerRotation.kXYZ eRoll.reorderIt(twistOrder) # Non-Roll orientation mtxFn = om2.MTransformationMatrix() mtxFn.rotateBy(eRoll, om2.MSpace.kWorld) mRoll = mtxFn.asMatrix() qNonRoll = om2.MQuaternion() nAim = om2.MVector(mRoll[0], mRoll[1], mRoll[2]) nAim.normalize() nAimAxis = om2.MVector.kXaxisVector qAim = om2.MQuaternion(nAimAxis, nAim) qNonRoll *= qAim if useUpObj: vUp = om2.MVector( dataBlock.inputValue(TwistExtractor.inUpVec).asFloat3()) nNormal = vUp - ((vUp * nAim) * nAim) nNormal.normalize() nUp = om2.MVector.kYaxisVector.rotateBy(qAim) angle = nUp.angle(nNormal) qNormal = om2.MQuaternion(angle, nAim) if not nNormal.isEquivalent(nUp.rotateBy(qNormal), 1.0e-5): angle = 2.0 * kPI - angle qNormal = om2.MQuaternion(angle, nAim) qNonRoll *= qNormal eNonRoll = qNonRoll.asEulerRotation() eNonRoll = om2.MEulerRotation(eNonRoll.x, eNonRoll.y, eNonRoll.z, twistOrder) # Extract Twist from orientations qRoll = eRoll.asQuaternion() qExtract180 = qNonRoll * qRoll.inverse() eExtract180 = qExtract180.asEulerRotation() twist = -eExtract180.x if revTwist: twist *= -1.0 # Output Twist if plug == TwistExtractor.outTwist: outTwistHdle = dataBlock.outputValue(TwistExtractor.outTwist) outTwistHdle.setMAngle(om2.MAngle(twist)) outTwistHdle.setClean() # Output Twist Distribution if plug == TwistExtractor.outTwistDist: invDist = dataBlock.inputValue(TwistExtractor.inRevDist).asBool() outTwistDistHdle = dataBlock.outputArrayValue( TwistExtractor.outTwistDist) outputs = len(outTwistDistHdle) step = twist / (outputs - 1) if outputs > 1 else twist outList = [] outList.extend(range(outputs)) if not invDist: outList.reverse() # pylint: disable=consider-using-enumerate for i in range(len(outList)): outTwistDistHdle.jumpToLogicalElement(i) resultHdle = outTwistDistHdle.outputValue() result = step * outList[i] if outputs > 1 else twist resultHdle.setMAngle(om2.MAngle(result)) outTwistDistHdle.setAllClean() return
def compute(self, plug, dataBlock): """ Node computation method: * plug is a connection point related to one of our node attributes (either an input or an output). * dataBlock contains the data on which we will base our computations. """ # pylint: disable=R0201 blender = dataBlock.inputValue(BlendTransform.inBlender).asFloat() if plug == BlendTransform.outTrans: trans1Handle = dataBlock.inputArrayValue(BlendTransform.inTrans1) trans2Handle = dataBlock.inputArrayValue(BlendTransform.inTrans2) outTransHandle = dataBlock.outputArrayValue( BlendTransform.outTrans) outList = [] for i in range(min(len(trans1Handle), len(trans2Handle))): trans1Handle.jumpToLogicalElement(i) trans2Handle.jumpToLogicalElement(i) vTrans1 = trans1Handle.inputValue().asFloatVector() vTrans2 = trans2Handle.inputValue().asFloatVector() vOut = (1.0 - blender) * vTrans1 + blender * vTrans2 outList.append(vOut) for i in range(len(outTransHandle)): outTransHandle.jumpToLogicalElement(i) resultHandle = outTransHandle.outputValue() if i < len(outTransHandle) and i < len(outList): resultHandle.setMFloatVector(outList[i]) else: resultHandle.setMFloatVector(om2.MFloatVector()) outTransHandle.setAllClean() elif plug == BlendTransform.outRot: rotInterp = dataBlock.inputValue( BlendTransform.inRotInterp).asShort() rot1Handle = dataBlock.inputArrayValue(BlendTransform.inRot1) rot2Handle = dataBlock.inputArrayValue(BlendTransform.inRot2) outRotHandle = dataBlock.outputArrayValue(BlendTransform.outRot) rotOrder1Handle = dataBlock.inputArrayValue( BlendTransform.inRot1Order) rotOrder2Handle = dataBlock.inputArrayValue( BlendTransform.inRot2Order) outRotOrderHandle = dataBlock.inputArrayValue( BlendTransform.inOutRotOrder) outList = [] for i in range(min(len(rot1Handle), len(rot2Handle))): rot1Handle.jumpToLogicalElement(i) rot2Handle.jumpToLogicalElement(i) rotOrder1 = BlendTransform.checkRotateOrderArrayHandle( rotOrder1Handle, i) rotOrder2 = BlendTransform.checkRotateOrderArrayHandle( rotOrder2Handle, i) outRotOrder = BlendTransform.checkRotateOrderArrayHandle( outRotOrderHandle, i) rot1 = rot1Handle.inputValue().asVector() rot2 = rot2Handle.inputValue().asVector() eRot1 = om2.MEulerRotation(rot1, rotOrder1) eRot2 = om2.MEulerRotation(rot2, rotOrder2) eRot1.reorderIt(outRotOrder) eRot2.reorderIt(outRotOrder) if rotInterp == 0: vRot1 = eRot1.asVector() vRot2 = eRot2.asVector() vOut = (1.0 - blender) * vRot1 + blender * vRot2 else: qRot1 = eRot1.asQuaternion() qRot2 = eRot2.asQuaternion() eSlerp = om2.MQuaternion.slerp(qRot1, qRot2, blender).asEulerRotation() eSlerp.reorderIt(outRotOrder) vOut = eSlerp.asVector() outList.append(vOut) for i in range(len(outRotHandle)): outRotHandle.jumpToLogicalElement(i) resultHandle = outRotHandle.outputValue() if i < len(outRotHandle) and i < len(outList): resultHandle.setMVector(outList[i]) else: resultHandle.setMVector(om2.MVector()) outRotHandle.setAllClean() elif plug == BlendTransform.outSca: sca1Handle = dataBlock.inputArrayValue(BlendTransform.inSca1) sca2Handle = dataBlock.inputArrayValue(BlendTransform.inSca2) outScaHandle = dataBlock.outputArrayValue(BlendTransform.outSca) outList = [] for i in range(min(len(sca1Handle), len(sca2Handle))): sca1Handle.jumpToLogicalElement(i) sca2Handle.jumpToLogicalElement(i) vSca1 = sca1Handle.inputValue().asFloatVector() vSca2 = sca2Handle.inputValue().asFloatVector() vOut = (1.0 - blender) * vSca1 + blender * vSca2 outList.append(vOut) for i in range(len(outScaHandle)): outScaHandle.jumpToLogicalElement(i) resultHandle = outScaHandle.outputValue() if i < len(outScaHandle) and i < len(outList): resultHandle.setMFloatVector(outList[i]) else: resultHandle.setMFloatVector(om2.MFloatVector()) outScaHandle.setAllClean() elif plug in (BlendTransform.outVis, BlendTransform.outRevVis): outVisHandle = dataBlock.outputValue(BlendTransform.outVis) outRevVisHandle = dataBlock.outputValue(BlendTransform.outRevVis) vis, revVis = BlendTransform.visibilityCalculation(blender) outVisHandle.setBool(vis) outRevVisHandle.setBool(revVis) outVisHandle.setClean() outRevVisHandle.setClean()
def compute(self, plug, dataBlock): """ Node computation method: * plug is a connection point related to one of our node attributes (either an input or an output). * dataBlock contains the data on which we will base our computations. """ # pylint: disable=no-self-use if plug != HelperJoint.outTransform: return om2.kUnknownParameter mSource = dataBlock.inputValue(HelperJoint.inSource).asMatrix() mtxFn = om2.MTransformationMatrix(mSource) mtxFn.setScale([1.0, 1.0, 1.0], om2.MSpace.kTransform) mSource = mtxFn.asMatrix() mSourceParent = dataBlock.inputValue(HelperJoint.inSourceParent).asMatrix() mParInv = dataBlock.inputValue(HelperJoint.inParInvMtx).asMatrix() sourceParSca = dataBlock.inputValue(HelperJoint.inSourceParSca).asFloat3() mtxFn = om2.MTransformationMatrix() mtxFn.scaleBy(sourceParSca, om2.MSpace.kTransform) mInvSca = mtxFn.asMatrix() targetListHandle = dataBlock.inputArrayValue(HelperJoint.inTargetList) outputList = [] for i in range(len(targetListHandle)): targetListHandle.jumpToLogicalElement(i) targetHandle = targetListHandle.inputValue() vPosOffset = om2.MVector(targetHandle.child(HelperJoint.inPositionOffset).asFloat3()) eRotOffset = om2.MEulerRotation(targetHandle.child(HelperJoint.inRotationOffset).asDouble3()) angle = targetHandle.child(HelperJoint.inRotAngle).asAngle().asRadians() restAngle = targetHandle.child(HelperJoint.inRestAngle).asAngle().asRadians() rotInterp = targetHandle.child(HelperJoint.inRotInterp).asFloat() posMult = targetHandle.child(HelperJoint.inPosMult).asFloat() negMult = targetHandle.child(HelperJoint.inNegMult).asFloat() mPositionOffset = om2.MMatrix() mPositionOffset[12] = vPosOffset.x mPositionOffset[13] = vPosOffset.y mPositionOffset[14] = vPosOffset.z multTranslation = abs(angle) * posMult if angle < restAngle: multTranslation = abs(angle) * negMult vPosOffset.normalize() mMultiplier = om2.MMatrix() mMultiplier[12] = vPosOffset.x * multTranslation mMultiplier[13] = vPosOffset.y * multTranslation mMultiplier[14] = vPosOffset.z * multTranslation mTargetPoint = mMultiplier * mPositionOffset * mSource mTargetOrient = mInvSca * (mSource * (1.0 - rotInterp)) + (mSourceParent * rotInterp) vResultPos = om2.MVector(mTargetPoint[12], mTargetPoint[13], mTargetPoint[14]) mtxFn = om2.MTransformationMatrix(mTargetOrient) eResultOri = eRotOffset + mtxFn.rotation(asQuaternion=False) mtxFn = om2.MTransformationMatrix() mtxFn.setRotation(eResultOri) mtxFn.setTranslation(vResultPos, om2.MSpace.kTransform) mResult = mtxFn.asMatrix() * mParInv outputList.append(mResult) outTransHandle = dataBlock.outputArrayValue(HelperJoint.outTransform) for i in range(len(outTransHandle)): outTransHandle.jumpToLogicalElement(i) resultHandle = outTransHandle.outputValue() if i < len(outTransHandle) and i < len(outputList): resultHandle.setMMatrix(outputList[i]) else: resultHandle.setMMatrix(om2.MMatrix.kIdentity)
def compute(self, plug, dataBlock): """ Node computation method: * plug is a connection point related to one of our node attributes (either an input or an output). * dataBlock contains the data on which we will base our computations. """ # pylint: disable=no-self-use if plug != AimConstraint.outConstraint: return om2.kUnknownParameter upVecType = dataBlock.inputValue(AimConstraint.inUpVecType).asShort() eOffset = om2.MEulerRotation( dataBlock.inputValue(AimConstraint.inOffset).asDouble3()) qOffset = eOffset.asQuaternion() mTargetW = dataBlock.inputValue(AimConstraint.inTargetWMtx).asMatrix() targetWeight = dataBlock.inputValue( AimConstraint.inTargetWeight).asDouble() mConstW = dataBlock.inputValue(AimConstraint.inConstWMtx).asMatrix() mConstParInv = dataBlock.inputValue( AimConstraint.inConstParInvMtx).asMatrix() eConstJntOri = om2.MEulerRotation( dataBlock.inputValue(AimConstraint.inConstJntOri).asDouble3()) qConstJntOri = eConstJntOri.asQuaternion() constRotOrder = dataBlock.inputValue( AimConstraint.inConstRotOrder).asShort() vTarget = om2.MVector(mTargetW[12], mTargetW[13], mTargetW[14]) vConst = om2.MVector(mConstW[12], mConstW[13], mConstW[14]) mtxFn = om2.MTransformationMatrix(mConstParInv) qConstParInv = mtxFn.rotation(asQuaternion=True) primAxis = om2.MVector.kXaxisVector secAxis = om2.MVector.kYaxisVector qAimConst = om2.MQuaternion() nAim = vTarget - vConst nAim.normalize() qAim = om2.MQuaternion(primAxis, nAim) qAimConst *= qAim if upVecType != 0: if upVecType == 1: # World Up nWorldUp = om2.MVector( dataBlock.inputValue( AimConstraint.inWorldUpVector).asFloat3()) nWorldUp.normalize() vUp = nWorldUp elif upVecType == 2: # Object Up mWorldUp = dataBlock.inputValue( AimConstraint.inWorldUpMtx).asMatrix() vWorldUp = om2.MVector(mWorldUp[12], mWorldUp[13], mWorldUp[14]) vUp = vWorldUp - vConst elif upVecType == 3: # Angle Up angleUp = dataBlock.inputValue( AimConstraint.inAngleUp).asAngle().asRadians() qTwist = om2.MQuaternion(angleUp, nAim) vUp = secAxis.rotateBy(qTwist) nNormal = vUp - ((vUp * nAim) * nAim) nNormal.normalize() nUp = secAxis.rotateBy(qAim) angle = nUp.angle(nNormal) qNormal = om2.MQuaternion(angle, nAim) if not nNormal.isEquivalent(nUp.rotateBy(qNormal), 1.0e-5): angle = 2.0 * math.pi - angle qNormal = om2.MQuaternion(angle, nAim) qAimConst *= qNormal qResult = om2.MQuaternion() qResult *= qOffset.invertIt() qResult *= qAimConst qResult *= qConstParInv qResult *= qConstJntOri.invertIt() eResult = qResult.asEulerRotation() eResult.reorderIt(constRotOrder) eResult *= targetWeight vResult = eResult.asVector() outConstraintHandle = dataBlock.outputValue( AimConstraint.outConstraint) outConstraintHandle.setMVector(vResult) outConstraintHandle.setClean()
def compute(self, plug, dataBlock): """ Node computation method: * plug is a connection point related to one of our node attributes (either an input or an output). * dataBlock contains the data on which we will base our computations. """ if plug != IKVChainSolver.outChain: return om2.kUnknownParameter # Get Basis Quaternion mRoot = dataBlock.inputValue(IKVChainSolver.inRoot).asMatrix() mHandle = dataBlock.inputValue(IKVChainSolver.inHandle).asMatrix() mPoleVector = dataBlock.inputValue( IKVChainSolver.inPoleVector).asMatrix() pvMode = dataBlock.inputValue(IKVChainSolver.inPvMode).asShort() prefAngle = dataBlock.inputValue( IKVChainSolver.inPreferredAngle).asAngle().asRadians() twist = dataBlock.inputValue( IKVChainSolver.inTwist).asAngle().asRadians() snap = dataBlock.inputValue(IKVChainSolver.inSnapUpVector).asFloat() mSnap = dataBlock.inputValue(IKVChainSolver.inSnap).asMatrix() flip = dataBlock.inputValue(IKVChainSolver.inFlip).asBool() vRoot = om2.MVector(mRoot[12], mRoot[13], mRoot[14]) vHandle = om2.MVector(mHandle[12], mHandle[13], mHandle[14]) vPoleVector = om2.MVector(mPoleVector[12], mPoleVector[13], mPoleVector[14]) vSnap = om2.MVector(mSnap[12], mSnap[13], mSnap[14]) primAxis = om2.MVector.kXaxisVector secAxis = om2.MVector.kYaxisVector if flip: primAxis = -om2.MVector.kXaxisVector secAxis = -om2.MVector.kYaxisVector binAxis = primAxis ^ secAxis qBasis = om2.MQuaternion() vAim = vHandle - vRoot nAim = vAim.normal() qAim = om2.MQuaternion(primAxis, nAim) qBasis *= qAim vStartSnap = vSnap - vRoot vEndSnap = vSnap - vHandle if pvMode == 0: vUp = vPoleVector - vRoot else: qTwist = om2.MQuaternion(prefAngle + twist, nAim) vUp = secAxis.rotateBy(qTwist) nNormalPole = vUp - ((vUp * nAim) * nAim) nNormalPole.normalize() if snap > 0.0: nNormalSnap = vStartSnap - ((vStartSnap * nAim) * nAim) nNormalSnap.normalize() nNormal = (1.0 - snap) * nNormalPole + snap * nNormalSnap else: nNormal = nNormalPole nUp = secAxis.rotateBy(qAim) angle = nUp.angle(nNormal) qNormal = om2.MQuaternion(angle, nAim) if not nNormal.isEquivalent(nUp.rotateBy(qNormal), 1.0e-5): angle = 2.0 * math.pi - angle qNormal = om2.MQuaternion(angle, nAim) qBasis *= qNormal # Solver Triangle restStartLen = dataBlock.inputValue( IKVChainSolver.inRestLenStart).asFloat() restEndLen = dataBlock.inputValue( IKVChainSolver.inRestLenEnd).asFloat() compressionLimit = dataBlock.inputValue( IKVChainSolver.inCompressionLimit).asFloat() softVal = dataBlock.inputValue(IKVChainSolver.inSoftness).asFloat() startSnapLen = vStartSnap.length() endSnapLen = vEndSnap.length() startLen = (1.0 - snap) * restStartLen + snap * startSnapLen endLen = (1.0 - snap) * restEndLen + snap * endSnapLen chainLen = (1.0 - snap) * (restStartLen + restEndLen) + snap * ( startSnapLen + endSnapLen) handleLen = vAim.length() rigidLen = max(min(handleLen, chainLen), chainLen * compressionLimit) dc = chainLen da = (1.0 - softVal) * dc if handleLen > da and softVal > 0.0: ds = dc - da softLen = ds * (1.0 - math.pow(math.e, (da - handleLen) / ds)) + da solverLen = (1.0 - snap) * softLen + snap * rigidLen else: solverLen = rigidLen # Pre Calculations startLenSquared = math.pow(startLen, 2.0) endLenSquared = math.pow(endLen, 2.0) solverLenSquared = math.pow(solverLen, 2.0) stretch = dataBlock.inputValue(IKVChainSolver.inStretch).asDouble() squashMultStart = dataBlock.inputValue( IKVChainSolver.inSquashMultStart).asFloat2() squashMultEnd = dataBlock.inputValue( IKVChainSolver.inSquashMultEnd).asFloat2() if stretch > 0.0: clampStretch = dataBlock.inputValue( IKVChainSolver.inClampStretch).asDouble() clampValue = dataBlock.inputValue( IKVChainSolver.inClampValue).asDouble() squash = dataBlock.inputValue(IKVChainSolver.inSquash).asDouble() if handleLen > da and softVal > 0.0: scaleFactor = handleLen / solverLen else: scaleFactor = handleLen / chainLen if handleLen >= da: clampFactor = ( 1.0 - clampStretch) * scaleFactor + clampStretch * min( scaleFactor, clampValue) stretchFactor = (1.0 - stretch) + stretch * clampFactor else: stretchFactor = 1.0 squashFactor = (1.0 - squash) + squash * (1.0 / math.sqrt(stretchFactor)) else: stretchFactor = 1.0 squashFactor = 1.0 hierarchyMode = dataBlock.inputValue( IKVChainSolver.inHierarchyMode).asBool() useScale = dataBlock.inputValue(IKVChainSolver.inUseScale).asBool() outChainHandle = dataBlock.outputArrayValue(IKVChainSolver.outChain) offsetHandle = dataBlock.inputArrayValue(IKVChainSolver.inOffset) jntOriHandle = dataBlock.inputArrayValue(IKVChainSolver.inJntOri) mParInv = dataBlock.inputValue(IKVChainSolver.inParInvMtx).asMatrix() srtList = [] offsetList = [] jntOriList = [] for i in range(len(offsetHandle)): offsetHandle.jumpToLogicalElement(i) eOff = om2.MEulerRotation(offsetHandle.inputValue().asDouble3()) qOff = eOff.asQuaternion() offsetList.append(qOff) for i in range(len(jntOriHandle)): jntOriHandle.jumpToLogicalElement(i) eOri = om2.MEulerRotation(jntOriHandle.inputValue().asDouble3()) qOri = eOri.asQuaternion() jntOriList.append(qOri) # First Output # Scale firstStretch = stretchFactor firstScaX = firstStretch if not useScale: firstStretch = 1.0 firstSquash = [ squashFactor * squashMultStart[0], squashFactor * squashMultStart[1] ] firstSca = [firstStretch, firstSquash[0], firstSquash[1]] # Rotation betaCosPure = (startLenSquared + solverLenSquared - endLenSquared) / (2.0 * startLen * solverLen) betaCos = min(max(betaCosPure, -1.0), 1.0) beta = math.acos(betaCos) qBeta = om2.MQuaternion(beta, binAxis) qFirstRotW = qBeta * qBasis qFirstRot = om2.MQuaternion() if len(offsetList) >= 1: qFirstRot *= offsetList[0].invertIt() qFirstRot *= qFirstRotW if len(jntOriList) >= 1: qFirstRot *= jntOriList[0].invertIt() # Translation vFirstPos = vRoot # Matrix Output mtxFn = om2.MTransformationMatrix() mtxFn.setScale(firstSca, om2.MSpace.kTransform) mtxFn.setRotation(qFirstRot) mtxFn.setTranslation(vFirstPos, om2.MSpace.kTransform) mFirst = mtxFn.asMatrix() mFirst *= mParInv srtList.append(mFirst) # Second Output # Scale secondStretch = stretchFactor secondScaX = secondStretch if not useScale: secondStretch = 1.0 secondSquash = [ squashFactor * squashMultEnd[0], squashFactor * squashMultEnd[1] ] secondSca = [secondStretch, secondSquash[0], secondSquash[1]] # Rotation gammaCosPure = (startLenSquared + endLenSquared - solverLenSquared) / (2.0 * startLen * endLen) gammaCos = min(max(gammaCosPure, -1.0), 1.0) gamma = math.acos(gammaCos) gammaCmp = gamma + beta - math.pi qGamma = om2.MQuaternion(gammaCmp, binAxis) qSecondRotW = qGamma * qBasis qSecondRot = om2.MQuaternion() if len(offsetList) >= 2: qSecondRot *= offsetList[1].invertIt() qSecondRot *= qSecondRotW if hierarchyMode: qSecondRot *= qFirstRotW.invertIt() if len(offsetList) >= 1: qSecondRot *= offsetList[0].invertIt() if len(jntOriList) >= 2: qSecondRot *= jntOriList[1].invertIt() # Translation if hierarchyMode: vSecondPos = primAxis * startLen if not useScale: vSecondPos *= firstScaX else: vSecondOri = nAim.rotateBy(om2.MQuaternion( beta, nAim ^ nNormal)) * startLen if not useScale: vSecondOri *= firstScaX vSecondPos = vRoot + vSecondOri # Matrix Output mtxFn = om2.MTransformationMatrix() mtxFn.setScale(secondSca, om2.MSpace.kTransform) mtxFn.setRotation(qSecondRot) mtxFn.setTranslation(vSecondPos, om2.MSpace.kTransform) mSecond = mtxFn.asMatrix() if not hierarchyMode: mSecond *= mParInv srtList.append(mSecond) # Third Output # Rotation qThirdRot = qBasis if hierarchyMode: qThirdRot *= qSecondRotW.invertIt() if len(offsetList) >= 2: qThirdRot *= offsetList[1].invertIt() # Translation if hierarchyMode: vThirdPos = primAxis * endLen if not useScale: vThirdPos *= secondScaX else: vThirdPos = vRoot + nAim * solverLen if not useScale: vThirdPos = vRoot + nAim * solverLen * stretchFactor # Matrix Output mtxFn = om2.MTransformationMatrix() mtxFn.setRotation(qThirdRot) mtxFn.setTranslation(vThirdPos, om2.MSpace.kTransform) mThird = mtxFn.asMatrix() if not hierarchyMode: mThird *= mParInv srtList.append(mThird) # Set outputs for i in range(len(outChainHandle)): outChainHandle.jumpToLogicalElement(i) resultHandle = outChainHandle.outputValue() if i < len(outChainHandle) and i < len(srtList): resultHandle.setMMatrix(srtList[i]) else: resultHandle.setMMatrix(om2.MMatrix.kIdentity) outChainHandle.setAllClean()
def compute(self, plug, dataBlock): """ Node computation method: * plug is a connection point related to one of our node attributes (either an input or an output). * dataBlock contains the data on which we will base our computations. """ # pylint: disable=no-self-use eConstJntOri = om2.MEulerRotation( dataBlock.inputValue( ParentConstraint.inConstraintJntOri).asDouble3()) mConstParInv = dataBlock.inputValue( ParentConstraint.inConstraintParInvMtx).asMatrix() constRotOrder = dataBlock.inputValue( ParentConstraint.inConstraintRotOrder).asShort() constParSca = dataBlock.inputValue( ParentConstraint.inConstraintParSca).asFloat3() targetListHandle = dataBlock.inputArrayValue( ParentConstraint.inTargetList) mTargetsAdded = om2.MMatrix() mtxFn = om2.MTransformationMatrix() mtxFn.scaleBy(constParSca, om2.MSpace.kTransform) mInvSca = mtxFn.asMatrix() for i in range(len(targetListHandle)): targetListHandle.jumpToLogicalElement(i) targetHandle = targetListHandle.inputValue() # targetJntOri = om2.MEulerRotation(targetHandle.child(ParentConstraint.inTargetJntOri).asDouble3()) # targetRotOrder = targetHandle.child(ParentConstraint.inTargetRotOrder).asShort() mTargetW = targetHandle.child( ParentConstraint.inTargetWorldMatrix).asMatrix() mOffset = targetHandle.child( ParentConstraint.inTargetOffset).asMatrix() targetWeight = targetHandle.child( ParentConstraint.inTargetWeight).asFloat() mTarget = mOffset * (mTargetW * targetWeight) if mTargetsAdded == om2.MMatrix(): mTargetsAdded = mTarget else: mTargetsAdded += mTarget mResult = mTargetsAdded * mConstParInv * mInvSca if plug == ParentConstraint.outConstTrans: outTransHandle = dataBlock.outputValue( ParentConstraint.outConstTrans) outTrans = om2.MFloatVector(mResult[12], mResult[13], mResult[14]) outTransHandle.setMFloatVector(outTrans) outTransHandle.setClean() if plug == ParentConstraint.outConstRot: outRotHandle = dataBlock.outputValue(ParentConstraint.outConstRot) mtxFn = om2.MTransformationMatrix(mResult) eRotMtx = mtxFn.rotation(asQuaternion=False) qRotMtx = eRotMtx.asQuaternion() qConstJntOri = eConstJntOri.asQuaternion() qOutRot = qRotMtx * qConstJntOri.invertIt() outRot = qOutRot.asEulerRotation().reorderIt(constRotOrder) outRotHandle.setMVector(outRot.asVector()) outRotHandle.setClean() if plug == ParentConstraint.outConstSca: outScaHandle = dataBlock.outputValue(ParentConstraint.outConstSca) mtxFn = om2.MTransformationMatrix(mResult) outSca = mtxFn.scale(om2.MSpace.kWorld) outScaHandle.set3Float(outSca[0], outSca[1], outSca[2]) outScaHandle.setClean()