def __init__(self, position=None, color=None, size=2): super(PointPrim, self).__init__() position = om2.MVector() if position is None else om2.MVector(position) self.transform.setTranslation(position, om2.MSpace.kWorld) # `color` as a tuple of floats representing RGB values (normalized). self.color = color or COLOR_BLACK self.size = size
def linearInterpolate(t, p0, p1): """ Performs a linear interpolation between p0 and p1. """ if _isIterable(p0): p0 = om2.MVector(p0) p1 = om2.MVector(p1) return p0 + ((p1 - p0) * t)
def update(self): super(VectorPrim, self).update() # update the line along the length of the vector self.body.color = self.color self.body.transform = self.transform self.body.transform.setScale((self.size, self.size, self.size), om2.MSpace.kWorld) self.body.update() # update the header of the vector (arrow) self.head.color = self.color self.head.transform = self.body.transform m_vector = om2.MVector(self.body._drawPoints[1]) m_vector -= self.transform.translation(om2.MSpace.kWorld) m_vectorX = om2.MVector(1, 0, 0) m_rot = m_vectorX.rotateTo(m_vector) self.head.transform.setRotation(m_rot)
def draw(self, view, path, style, status): """ Draw custom geometry in the viewport using OpenGL calls. * view [M3dView] is a 3D view that is being drawn into. * path [MDagPath] to the parent (transform node) of this locator in the DAG. To obtain the locator shape node, use MDagPath::extendToShape() if there is only one shape node under the transform or MDagPath::extendToShapeDirectlyBelow(unsigned int index) with the shape index if there are multiple shapes under the transform. * style [M3dView.DisplayStyle] is the style to draw object in. * status [M3dView.DisplayStatus] is the selection status of the object. """ # pylint: disable=unused-argument thisMob = self.thisMObject() size = om2.MPlug(thisMob, TestLocator.inSize).asDouble() view.beginGL() glRenderer = omr1.MHardwareRenderer.theRenderer() glFT = glRenderer.glFunctionTable() glFT.glPushAttrib(omr1.MGL_CURRENT_BIT) glFT.glDisable(omr1.MGL_CULL_FACE) if status == omui2.M3dView.kActive: glFT.glColor3f(0.3, 1.0, 1.0) elif status == omui2.M3dView.kLead: glFT.glColor3f(1.0, 1.0, 1.0) elif status == omui2.M3dView.kDormant: glFT.glColor3f(1.0, 1.0, 0.0) vPoint1 = om2.MVector(1.0, 0.0, -1.0) * size vPoint2 = om2.MVector(-1.0, 0.0, -1.0) * size vPoint3 = om2.MVector(-1.0, 0.0, 1.0) * size vPoint4 = om2.MVector(1.0, 0.0, 1.0) * size glFT.glBegin(omr1.MGL_QUADS) glFT.glVertex3f(vPoint1.x, vPoint1.y, vPoint1.z) glFT.glVertex3f(vPoint2.x, vPoint2.y, vPoint2.z) glFT.glVertex3f(vPoint3.x, vPoint3.y, vPoint3.z) glFT.glVertex3f(vPoint4.x, vPoint4.y, vPoint4.z) glFT.glEnd() glFT.glPopAttrib() view.endGL()
def pointsAlongVector( start='', end='', divisions=2, bias=0 ): ''' returns a list of points that lie on a line between start and end 'divisions' specifies the number of points to return. divisions = 2 (default) will return the start and end points with one intermediate point: [ p1(start), p2, p3(end) ] start and end can be supplied as lists, tuples or nodes. If they are not supplied, and 2 scene nodes are selected will attempt to use their world space positions as start and end creates a vector by subtracting end from start stores length of vector normalizes vector multiplies normalized vector by length / divisions bias specifies weight of point distribution towards start or end. Positive values favour end, negative favour start ''' startPos, endPos = getStartAndEnd(start, end) if not startPos or not endPos: return 'pointsAlongVector: Cannot determine start and end points' startVec = om2.MVector(startPos[0], startPos[1], startPos[2]) endVec = om2.MVector(endPos[0], endPos[1], endPos[2]) newVec = endVec - startVec segLength = (newVec.length() / divisions) / newVec.length() #newVec.normalize() points = [] points.append(tuple(startPos)) segLengths = [segLength * each for each in range(divisions)] if bias: for i in range(divisions): #paramVals[i] - pow(paramVals[i], 1 + bias) segLengths[i] += segLengths[i] - pow(segLengths[i], 1 + bias) for p in range( 1, divisions ): point = (newVec * segLengths[p]) + startVec points.append((point.x, point.y, point.z)) points.append(tuple(endPos)) return points
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 != PoleVectorConstraint.outConstraint: return om2.kUnknownParameter mRoot = dataBlock.inputValue( PoleVectorConstraint.inRootWMtx).asMatrix() mTarget = dataBlock.inputValue( PoleVectorConstraint.inTargetWMtx).asMatrix() mConstParInv = dataBlock.inputValue( PoleVectorConstraint.inConstParInvMtx).asMatrix() targetWeight = dataBlock.inputValue( PoleVectorConstraint.inTargetWeight).asDouble() vRest = om2.MVector( dataBlock.inputValue( PoleVectorConstraint.inRestPosition).asFloat3()) normalize = dataBlock.inputValue( PoleVectorConstraint.inNormalizeOutput).asBool() vRoot = om2.MVector(mRoot[12], mRoot[13], mRoot[14]) vTarget = om2.MVector(mTarget[12], mTarget[13], mTarget[14]) vPoleDirection = (vTarget - vRoot) * mConstParInv vRestDirection = (vRest - vRoot) * mConstParInv vPole = (1.0 - targetWeight) * vRestDirection + targetWeight * vPoleDirection vResult = om2.MFloatVector(vPole) if normalize: vResult.normalize() outConstHdle = dataBlock.outputValue( PoleVectorConstraint.outConstraint) outConstHdle.setMFloatVector(vResult) outConstHdle.setClean()
def prepareForDraw(self, objPath, cameraPath, frameContext, oldData): """ Called by Maya each time the object needs to be drawn. Any data needed from the Maya dependency graph must be retrieved and cached in this stage. Returns the data to be passed to the draw callback method. * objPath [MDagPath] is the path to the object being drawn. * cameraPath [MDagPath] is the path to the camera that is being used to draw. * frameContext [MFrameContext] is the frame level context information. * oldData [MUserData] is the data cached by the previous draw of the instance. """ # pylint: disable=unused-argument data = oldData if not isinstance(data, TestLocatorData): data = TestLocatorData() node = objPath.node() size = om2.MPlug(node, TestLocator.inSize).asDouble() data.fDormantColor = om2.MColor([1.0, 1.0, 0.0]) data.fActiveColor = om2.MColor([0.3, 1.0, 1.0]) data.fLeadColor = om2.MColor([1.0, 1.0, 1.0]) data.fSize = size vPoint1 = om2.MVector(1.0, 0.0, -1.0) * size vPoint2 = om2.MVector(-1.0, 0.0, -1.0) * size vPoint3 = om2.MVector(-1.0, 0.0, 1.0) * size vPoint4 = om2.MVector(1.0, 0.0, 1.0) * size data.fQuadList.clear() data.fQuadList.append(om2.MPoint(vPoint1)) data.fQuadList.append(om2.MPoint(vPoint2)) data.fQuadList.append(om2.MPoint(vPoint3)) data.fQuadList.append(om2.MPoint(vPoint4)) data.fQuadList.append(om2.MPoint(vPoint1)) return data
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 __init__(self, vector, size=1.0, color=None): super(VectorPrim, self).__init__() self._size = size self.color = color or COLOR_BLACK # body line _points = ((0, 0, 0), vector) self.body = CurvePrim(_points, color=self.color) self.body.scale(self.size, self.size, self.size) # head line m_vector = om2.MVector(*vector) length = m_vector.length() headSize = 0.1 * length points = ((length - headSize, headSize, 0.0), (length, 0.0, 0.0), (length - headSize, -headSize, 0.0)) self.head = CurvePrim(points, color=self.color) self.isDirty = True # force to re-orient header
def bezierInterpolate(t, points): """ Performs a bezier interpolation (recursive). """ if not _isIterable(points): logger.error('Points is expected to be a secuence of points') return n = len(points) - 1 n_factorial = math.factorial(n) for i, p in enumerate(points): if not isinstance(p, om2.MVector): p = om2.MVector(p) k = n_factorial / float(math.factorial(i) * math.factorial(n - i)) b = (t**i) * (1 - t)**(n - i) v = p * b * k if i == 0: rval = v else: rval += v return rval
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 ctrlPntsHandle = dataBlock.inputArrayValue( QuadraticCurve.inControlPoints) ctrlPnts = om2.MPointArray() if len(ctrlPntsHandle) < 3: return for i in range(3): ctrlPntsHandle.jumpToLogicalElement(i) mCtrlPnt = ctrlPntsHandle.inputValue().asMatrix() ctrlPnt = om2.MPoint(mCtrlPnt[12], mCtrlPnt[13], mCtrlPnt[14]) ctrlPnts.append(ctrlPnt) crvKnots = om2.MDoubleArray([0, 0, 1, 1]) crvDegree = 2 crvForm = om2.MFnNurbsCurve.kOpen crvIs2d = False crvRational = False crvData = om2.MFnNurbsCurveData().create() crvFn = om2.MFnNurbsCurve(crvData) crvFn.create(ctrlPnts, crvKnots, crvDegree, crvForm, crvIs2d, crvRational, crvData) crvFn.updateCurve() if plug == QuadraticCurve.outCurve: outCurveHandle = dataBlock.outputValue(QuadraticCurve.outCurve) outCurveHandle.setMObject(crvData) outCurveHandle.setClean() elif plug == QuadraticCurve.outTransforms: outTransHandle = dataBlock.outputArrayValue( QuadraticCurve.outTransforms) lockLength = dataBlock.inputValue( QuadraticCurve.inLockLength).asFloat() restLength = dataBlock.inputValue( QuadraticCurve.inRestLength).asFloat() slide = dataBlock.inputValue(QuadraticCurve.inSlide).asFloat() numOutputs = len(outTransHandle) crvLength = crvFn.length() parRejected = crvFn.findParamFromLength(crvLength - restLength) stepFull = 1.0 / (numOutputs - 1) if numOutputs > 1 else 0.0 stepLock = crvFn.findParamFromLength(restLength) / ( numOutputs - 1) if numOutputs > 1 else 0.0 step = (1.0 - lockLength) * stepFull + lockLength * stepLock parSlide = parRejected * slide * lockLength for i in range(numOutputs): parameter = (step * i) # + parSlide pos = crvFn.getPointAtParam(parameter, om2.MSpace.kObject) vPos = om2.MVector(pos.x, pos.y, pos.z) mtx = [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, vPos.x, vPos.y, vPos.z, 1.0 ] mOut = om2.MMatrix(mtx) outTransHandle.jumpToLogicalElement(i) resultHandle = outTransHandle.outputValue() resultHandle.setMMatrix(mOut) outTransHandle.setAllClean() else: return om2.kUnknownParameter
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. """ 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 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. """ # 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 scale(self, x=0.0, y=0.0, z=0.0): if x == y == z == 0.0: return offset = om2.MVector(x, y, z) self.transform.scaleBy(offset, om2.MSpace.kWorld) self.isDirty = True
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 not dataBlock.isClean(SpaceConstraint.inSpace): # om2.MGlobal.displayInfo("\tSpace attribute is dirty.") # om2.MUserEventMessage.postUserEvent("preCompute", self) curSpace = dataBlock.inputValue(SpaceConstraint.inSpace).asShort() offsetMatchHdle = dataBlock.inputArrayValue( SpaceConstraint.inOffsetMatches) offsetHdle = dataBlock.inputArrayValue(SpaceConstraint.inOffset) targetHdle = dataBlock.inputArrayValue(SpaceConstraint.inTarget) offsetMatchList = [] offsetList = [] targetList = [] for i in range(len(offsetMatchHdle)): offsetMatchHdle.jumpToLogicalElement(i) mOffMatch = offsetMatchHdle.inputValue().asMatrix() offsetMatchList.append(mOffMatch) for i in range(len(offsetHdle)): offsetHdle.jumpToLogicalElement(i) mOff = offsetHdle.inputValue().asMatrix() offsetList.append(mOff) for i in range(len(targetHdle)): targetHdle.jumpToLogicalElement(i) mTgt = targetHdle.inputValue().asMatrix() targetList.append(mTgt) if len(offsetList) == 0 or len(targetList) == 0: mResult = om2.MMatrix() else: minRequired = min(len(offsetList), len(targetList)) - 1 if curSpace > minRequired: curSpace = minRequired mResult = offsetMatchList[curSpace] * offsetList[ curSpace] * targetList[curSpace] mtxFn = om2.MTransformationMatrix(mResult) if plug == SpaceConstraint.outConstTrans: vTransD = om2.MVector(mResult[12], mResult[13], mResult[14]) vTrans = om2.MFloatVector(vTransD) outTransHdle = dataBlock.outputValue(SpaceConstraint.outConstTrans) outTransHdle.setMFloatVector(vTrans) outTransHdle.setClean() if plug == SpaceConstraint.outConstRot: eRot = mtxFn.rotation(asQuaternion=False) outRotHdle = dataBlock.outputValue(SpaceConstraint.outConstRot) outRotHdle.setMVector(eRot.asVector()) outRotHdle.setClean() if plug == SpaceConstraint.outConstSca: outSca = mtxFn.scale(om2.MSpace.kWorld) outScaHdle = dataBlock.outputValue(SpaceConstraint.outConstSca) outScaHdle.set3Float(outSca[0], outSca[1], outSca[2]) outScaHdle.setClean()