def bakeManualRotateDelta(src, ctrl, presetStr): ''' When you need to apply motion from a skeleton that is completely different from a skeleton driven by the rig you're working with (transferring motion from old assets to newer assets for example) you can manually align the control to the joint and then use this function to generate offset rotations and bake a post trace cmd. ''' srcInvMat = Matrix(getAttr('%s.worldInverseMatrix' % src)) ctrlMat = Matrix(getAttr('%s.worldMatrix' % ctrl)) #generate the offset matrix as mat_o = ctrlMat * srcInvMat #now figure out the euler rotations for the offset ro = getAttr('%s.ro' % ctrl) rotDelta = constants.MATRIX_ROTATION_ORDER_CONVERSIONS_TO[ro](mat_o, True) #now get the positional delta posDelta = Vector(xform(src, q=True, ws=True, rp=True)) - Vector( xform(ctrl, q=True, ws=True, rp=True)) posDelta *= -1 ctrlParentInvMat = Matrix(getAttr('%s.parentInverseMatrix' % ctrl)) posDelta = posDelta * ctrlParentInvMat #construct a list to use for the format str formatArgs = tuple(rotDelta) + tuple(posDelta) #build the post trace cmd str PostTraceNode(ctrl).setCmd(presetStr % formatArgs) return rotDelta
def _asPy(self, size=4): values = [] for i in range(size): for j in range(size): values.append(self(i, j)) return Matrix(values, size)
def __asNice(self): values = [] for i in range(4): for j in range(4): values.append(self(i, j)) return Matrix(values)
def mirrorMatrix(matrix, axis=AX_X, orientAxis=AX_X): ''' axis is the axis things are flipped across orientAxis is the axis that gets flipped when mirroring orientations ''' assert isinstance(matrix, Matrix) mirroredMatrix = Matrix(matrix) #make sure we've been given a Axis instances... don't bother testing, just do it, and make it absolute (non-negative - mirroring in -x is the same as mirroring in x) mirrorAxis = abs(Axis(axis)) axisA = abs(Axis(orientAxis)) #flip all axes axisB, axisC = axisA.otherAxes() mirroredMatrix[axisB][mirrorAxis] = -matrix[axisB][mirrorAxis] mirroredMatrix[axisC][mirrorAxis] = -matrix[axisC][mirrorAxis] #the above flipped all axes - but this results in a changing of coordinate system handed-ness, so flip one of the axes back nonMirrorAxisA, nonMirrorAxisB = mirrorAxis.otherAxes() mirroredMatrix[axisA][ nonMirrorAxisA] = -mirroredMatrix[axisA][nonMirrorAxisA] mirroredMatrix[axisA][ nonMirrorAxisB] = -mirroredMatrix[axisA][nonMirrorAxisB] #if the input matrix was a 4x4 then mirror translation if matrix.size == 4: mirroredMatrix[3][mirrorAxis] = -matrix[3][mirrorAxis] return mirroredMatrix
def setWorldRotMatrix(obj, matrix): ''' given a world matrix, will set the transforms of the object ''' parentInvMatrix = Matrix(getAttr('%s.parentInverseMatrix' % obj)) localMatrix = matrix * parentInvMatrix setLocalRotMatrix(obj, localMatrix)
def getWorldRotMatrix(obj): ''' returns the world matrix for the given obj ''' worldMatrix = Matrix(getAttr('%s.worldMatrix' % obj), 4) worldMatrix.set_position((0, 0, 0)) return worldMatrix
def getLocalRotMatrix(obj): ''' returns the local matrix for the given obj ''' localMatrix = Matrix(getAttr('%s.matrix' % obj), 4) localMatrix.set_position((0, 0, 0)) return localMatrix
def compute(self, plug, dataBlock): dh_mirrorTranslation = dataBlock.inputValue(self.mirrorTranslation) mirrorTranslation = Axis(dh_mirrorTranslation.asShort()) inWorldMatrix = dataBlock.inputValue(self.inWorldMatrix).asMatrix() inParentInvMatrix = dataBlock.inputValue( self.inParentMatrixInv).asMatrix() dh_mirrorAxis = dataBlock.inputValue(self.mirrorAxis) axis = Axis(dh_mirrorAxis.asShort()) ### DEAL WITH ROTATION AND POSITION SEPARATELY ### R, S = inWorldMatrix.asPy( 3).decompose() #this gets just the 3x3 rotation and scale matrices x, y, z = R #extract basis vectors #mirror the rotation axes and construct the mirrored rotation matrix idxA, idxB = axis.otherAxes() x[idxA] = -x[idxA] x[idxB] = -x[idxB] y[idxA] = -y[idxA] y[idxB] = -y[idxB] z[idxA] = -z[idxA] z[idxB] = -z[idxB] #factor scale back into the matrix mirroredMatrix = Matrix(x + y + z, 3) * S mirroredMatrix = mirroredMatrix.expand(4) #now put the rotation matrix in the space of the target object dh_targetParentMatrixInv = dataBlock.inputValue( self.targetParentMatrixInv) tgtParentMatrixInv = dh_targetParentMatrixInv.asMatrix() matInv = tgtParentMatrixInv.asPy() #put the rotation in the space of the target's parent mirroredMatrix = mirroredMatrix * matInv #if there is a joint orient, make sure to compensate for it tgtJoX = dataBlock.inputValue(self.targetJointOrientX).asDouble() tgtJoY = dataBlock.inputValue(self.targetJointOrientY).asDouble() tgtJoZ = dataBlock.inputValue(self.targetJointOrientZ).asDouble() jo = Matrix.FromEulerXYZ(tgtJoX, tgtJoY, tgtJoZ) joInv = jo.inverse() joInv = joInv.expand(4) mirroredMatrix = mirroredMatrix * joInv #grab the rotation order of the target rotOrderIdx = dataBlock.inputValue(self.targetRotationOrder).asInt() #grab euler values R, S = mirroredMatrix.decompose( ) #we need to decompose again to extract euler angles... eulerXYZ = outX, outY, outZ = mayaRotationOrders[rotOrderIdx]( R) #R.ToEulerYZX() dh_outRX = dataBlock.outputValue(self.outRotateX) dh_outRY = dataBlock.outputValue(self.outRotateY) dh_outRZ = dataBlock.outputValue(self.outRotateZ) #set the rotation dh_outRX.setDouble(outX) dh_outRY.setDouble(outY) dh_outRZ.setDouble(outZ) dataBlock.setClean(plug) ### NOW DEAL WITH POSITION ### #set the position if mirrorTranslation == self.M_COPY: inLocalMatrix = inWorldMatrix * inParentInvMatrix pos = MPoint(inLocalMatrix(3, 0), inLocalMatrix(3, 1), inLocalMatrix(3, 2)) elif mirrorTranslation == self.M_INVERT: inLocalMatrix = inWorldMatrix * inParentInvMatrix pos = MPoint(-inLocalMatrix(3, 0), -inLocalMatrix(3, 1), -inLocalMatrix(3, 2)) elif mirrorTranslation == self.M_MIRROR: pos = MPoint(inWorldMatrix(3, 0), inWorldMatrix(3, 1), inWorldMatrix(3, 2)) pos = [pos.x, pos.y, pos.z] pos[axis] = -pos[axis] pos = MPoint(*pos) pos = pos * tgtParentMatrixInv else: return dh_outTX = dataBlock.outputValue(self.outTranslateX) dh_outTY = dataBlock.outputValue(self.outTranslateY) dh_outTZ = dataBlock.outputValue(self.outTranslateZ) dh_outTX.setDouble(pos[0]) dh_outTY.setDouble(pos[1]) dh_outTZ.setDouble(pos[2])