def updateTRS(self, expectedTRS, op, v, space=om.MSpace.kWorld): '''Update the expected vector based on given operation, vector and space The expectedTRS vector has 9 entries: * 0-2 The world position * 3-5 The world rotation (in degrees) * 6-8 The world scale The possible operations are move, rotate, and scale. The possible spaces are kObject and kWorld (default) ''' if (expectedTRS is None): expectedTRS = [None] * 9 # trs starts as the identity matrix # trs = om.MTransformationMatrix() # Add translation, rotation, and scale, in world space, to recreate # the last transformation matrix. # if (expectedTRS[0] is not None): trs.setTranslation( om.MVector(expectedTRS[0], expectedTRS[1], expectedTRS[2]), om.MSpace.kWorld) if (expectedTRS[3] is not None): trs.setRotation( om.MEulerRotation(radians(expectedTRS[3]), radians(expectedTRS[4]), radians(expectedTRS[5]))) if (expectedTRS[6] is not None): trs.setScale( om.MVector(expectedTRS[6], expectedTRS[7], expectedTRS[8]), om.MSpace.kWorld) # Apply the requested operation. If the space is kObject, and we had a # scale factor, we must counteract it to get the right matrix, by # dividing the translation vector by it (otherwise it ends up being # scaled twice, and the expected value is incorrect). # if op == self.move: if (space == om.MSpace.kObject and expectedTRS[6] is not None): trs.translateBy( om.MVector(v[0] / expectedTRS[6], v[1] / expectedTRS[7], v[2] / expectedTRS[8]), space) else: trs.translateBy(om.MVector(v[0], v[1], v[2]), space) elif op == self.rotate: trs.rotateBy( om.MEulerRotation(radians(v[0]), radians(v[1]), radians(v[2])), space) elif op == self.scale: trs.scaleBy(om.MVector(v[0], v[1], v[2]), space) # Recover the world space translate, rotate, and scale, and updated # the expected vector # expectedTRS[0:3] = trs.translation(om.MSpace.kWorld) r = trs.rotation().asVector() expectedTRS[3] = degrees(r[0]) expectedTRS[4] = degrees(r[1]) expectedTRS[5] = degrees(r[2]) expectedTRS[6:9] = trs.scale(om.MSpace.kWorld) return expectedTRS
def test_setRotation(self): con = control.Control(name="testControl") con.create(shape="arrow") con.setRotation(om2.MEulerRotation(10, 10, 10)) trans = om2.MFnTransform(con.dagPath.node()) rot = trans.rotation() self.assertEquals(rot, om2.MEulerRotation(10, 10, 10)) con.setRotation(om2.MEulerRotation(-10, -10, -10), cvs=True) # probably should test the cv locations self.assertEquals(trans.rotation(), om2.MEulerRotation(10, 10, 10))
def getObjectWorldOrientation(node): if(node is None): return None jointRot = getJointWorldOrientation(node) if isJoint(node) else om.MEulerRotation() rot = cmds.xform(node, query=True, translation=False, rotation=True, absolute=True) rotOrder = mayaMathUtil.nodeRotOrderToEulerRotOrder(cmds.xform(node, query=True, rotateOrder=True, absolute=True)) objRot = om.MEulerRotation(math.radians(rot[0]), math.radians(rot[1]), math.radians(rot[2]), rotOrder) return objRot * jointRot
def compute(self, plug, dataBlock): if plug is not self.expmap and plug not in self.expmapElement: return r = [0, 0, 0] for i in xrange(0, 3): rHandle = dataBlock.inputValue(mlEulerToExpmap.eulerAngles[i]) r[i] = rHandle.asDouble() roHandle = dataBlock.inputValue(mlEulerToExpmap.rotateOrder) rotateOrder = roHandle.asInt() eulerRotation = OpenMaya.MEulerRotation(r[0], r[1], r[2], rotateOrder) q = eulerRotation.asQuaternion() if q.w < 0: q = -q if math.fabs(q.w) > 1.0 - 1.0e-6: a = 0.0 isina = 0.0 else: a = math.acos(q.w) isina = a / math.sin(a) ln = (q.x * isina, q.y * isina, q.z * isina) for i in xrange(0, 3): outputHandle = dataBlock.outputValue( mlEulerToExpmap.expmapElement[i]) outputHandle.setDouble(ln[i]) dataBlock.setClean(plug)
def get_local_matrix(self, node, invertJointOrient=False): local_mx = cmds.xform(node, m=1, q=1) #ignore code below for now - that code will take joint orient into account return local_mx if invertJointOrient: # if it's a joint, lets remove the joint orient from the local matrix if cmds.nodeType(node) == "joint": selList = api.MGlobal.getSelectionListByName(node) dagPath = selList.getDagPath(0) parentMatrix = dagPath.exclusiveMatrix() worldMatrix = dagPath.inclusiveMatrix() jointOrient = cmds.getAttr(node + ".jointOrient")[0] x = math.radians(jointOrient[0]) y = math.radians(jointOrient[1]) z = math.radians(jointOrient[2]) joEuler = api.MEulerRotation(x, y, z) joMatrix = joEuler.asMatrix() localMatrix = worldMatrix * parentMatrix.inverse() orientLocalMatrix = localMatrix * joMatrix.inverse() # combine the orient local matrix and the translation which shouldn't be changed based on the orientation for i in range(12): localMatrix[i] = orientLocalMatrix[i] # set the local matrix to this local_mx = localMatrix return local_mx
def _mirror_rotation(parent_matrix, m_parent_matrix, rot): """this mirrors the rotation""" driver_mat_fn = api.MTransformationMatrix(api.MMatrix.kIdentity) # set the values to radians rot[0] = math.radians(rot[0]) rot[1] = math.radians(rot[1]) rot[2] = math.radians(rot[2]) euler = api.MEulerRotation(rot[0], rot[1], rot[2]) driver_mat_fn.setRotation(euler) driver_matrix = driver_mat_fn.asMatrix() world_matrix = driver_matrix * parent_matrix rot_matrix = parent_matrix.inverse() * world_matrix rot_matrix_fn = api.MTransformationMatrix(rot_matrix) rot = rot_matrix_fn.rotation(asQuaternion=True) rot.x = rot.x * -1.0 rot.w = rot.w * -1.0 rot_matrix = rot.asMatrix() final_rot_matrix = m_parent_matrix * rot_matrix * m_parent_matrix.inverse() rot_matrix_fn = api.MTransformationMatrix(final_rot_matrix) rot = rot_matrix_fn.rotation(asQuaternion=False) m_rot = api.MVector() m_rot[0] = math.degrees(rot[0]) m_rot[1] = math.degrees(rot[1]) m_rot[2] = math.degrees(rot[2]) return m_rot
def usdSceneItemRotation(item): prim = usdUtils.getPrimFromSceneItem(item) if not prim.HasAttribute('xformOp:rotateXYZ'): return proxyShapeXformFn.rotation(om.MSpace.kTransform) else: x,y,z = prim.GetAttribute('xformOp:rotateXYZ').Get() return proxyShapeXformFn.rotation(om.MSpace.kTransform) + om.MEulerRotation(radians(x), radians(y), radians(z))
def compute(self, plug, dataBlock): if plug is not self.rotate and plug not in self.eulerAngles: return rv = [0.0, 0.0, 0.0] for i in xrange(0, 3): inputHandle = dataBlock.inputValue( mlExpmapToEuler.expmapElement[i]) rv[i] = inputHandle.asDouble() orderHandle = dataBlock.inputValue(mlExpmapToEuler.rotateOrder) exHandle = dataBlock.outputValue(mlExpmapToEuler.eulerAngles[0]) eyHandle = dataBlock.outputValue(mlExpmapToEuler.eulerAngles[1]) ezHandle = dataBlock.outputValue(mlExpmapToEuler.eulerAngles[2]) mag = math.sqrt(rv[0] * rv[0] + rv[1] * rv[1] + rv[2] * rv[2]) if math.fabs(mag) < 1.0e-6: sina = 0 else: sina = math.sin(mag) / mag quat = OpenMaya.MQuaternion(rv[0] * sina, rv[1] * sina, rv[2] * sina, math.cos(mag)) order = orderHandle.asInt() euler = OpenMaya.MEulerRotation(0, 0, 0, order) euler *= quat exHandle.setDouble(euler.x) eyHandle.setDouble(euler.y) ezHandle.setDouble(euler.z) dataBlock.setClean(plug)
def flip_euler(euler, rotation_order): """Resolve flipping rotations in cases where flipping occurs on multiple different channels; middle rotations are offloaded to outer rotations. Args: euler(OpenMaya.MEulerRotation): rrotation to adjust for flipping. rotation_order(str): order in which channels are rotated eg. xyz. Returns: euler(OpenMaya.MEulerRotation): rotation adjusted for flipping channels. """ result = OpenMaya.MEulerRotation() inner_axis = rotation_order[0] middle_axis = rotation_order[1] outer_axis = rotation_order[2] inner_value = getattr(euler, inner_axis) + math.pi setattr(result, inner_axis, inner_value) outer_value = getattr(euler, outer_axis) + math.pi setattr(result, outer_axis, outer_value) middle_value = getattr(euler, middle_axis) * -1 + math.pi setattr(result, middle_axis, middle_value) return result
def _getLocalTransform(self): node = self.thisMObject() transformPlug = om.MPlug(node, self.transformAttr) transform = om.MFnMatrixData(transformPlug.asMObject()).matrix() mat = om.MTransformationMatrix(transform) # Apply local translation. localTranslatePlug = om.MPlug(node, self.localTranslateAttr) localTranslation = om.MVector( *[localTranslatePlug.child(idx).asFloat() for idx in range(3)]) mat.translateBy(localTranslation, om.MSpace.kObject) # Apply local rotation. localRotatePlug = om.MPlug(node, self.localRotateAttr) localRotatePlugs = [localRotatePlug.child(idx) for idx in range(3)] localRotate = om.MVector( * [localRotatePlugs[idx].asMAngle().asRadians() for idx in range(3)]) mat.rotateBy(om.MEulerRotation(localRotate), om.MSpace.kObject) # Apply local scale. scalePlug = om.MPlug(node, self.localScaleAttr) scale = om.MFnNumericData(scalePlug.asMObject()).getData() mat.scaleBy(scale, om.MSpace.kObject) return mat.asMatrix()
def aimNode(node,target, myAimAxis=[1,0,0], myUpAxis=[0,1,0], myUpDir=[0,0,1]): """rotate a transform to aim a target point Args: node (str): transform node name target (list): world space point expresed as [float, float, float] myAimAxis (list, optional): the axis that point to the target. Defaults to [1,0,0]. myUpAxis (list, optional): the axis up to stabilize the rotation. Defaults to [0,1,0]. myUpDir (list, optional): [description]. Defaults to [0,0,1]. """ selList = om.MSelectionList() selList.add(node) mdpThis = selList.getDagPath(0) mpTarget=om.MPoint(target) mmMatrix = mdpThis.inclusiveMatrix(); mmMatrixInverse = mmMatrix.inverse(); mpTargetInThisSpace=om.MPoint(mpTarget * mmMatrixInverse); mqToTarget=om.MQuaternion (om.MVector(myAimAxis).rotateTo(om.MVector(mpTargetInThisSpace))); # Apply that rotation to this node: mftThis=om.MFnTransform (mdpThis.transform()); mftThis.rotateBy(mqToTarget, om.MSpace.kPreTransform); mmMatrix = mdpThis.inclusiveMatrix(); mmMatrixInverse = mmMatrix.inverse(); mvUp=om.MVector(myUpDir) mpWorldUpInThisSpace=om.MPoint (mvUp * mmMatrixInverse); # Get the quaternion that describes the rotation to make the local up vector point to the world up vector: mqToWorldUp=om.MQuaternion (om.MVector(om.MVector(myUpAxis)).rotateTo(om.MVector(mpWorldUpInThisSpace))); merToWorldUp=om.MEulerRotation (mqToWorldUp.asEulerRotation()); merToWorldUp.y = 0.0; merToWorldUp.z = 0.0; # Apply that rotation to this node: mftThis.rotateBy(merToWorldUp, om.MSpace.kPreTransform);
def _assume_t_pose(self, segment): transformFn = self._segments[int(segment["@ID"])]["transformFn"] if self._up_axis == "y": translation = om.MVector( -float(segment["Position"]["@X"]) * self._unit_conversion, float(segment["Position"]["@Z"]) * self._unit_conversion, float(segment["Position"]["@Y"]) * self._unit_conversion, ) else: translation = om.MVector( float(segment["Position"]["@X"]) * self._unit_conversion, float(segment["Position"]["@Y"]) * self._unit_conversion, float(segment["Position"]["@Z"]) * self._unit_conversion, ) transformFn.setTranslation(translation, om.MSpace.kTransform) transformFn.setRotation( om.MEulerRotation( float(segment["Rotation"]["@X"]), float(segment["Rotation"]["@Y"]), float(segment["Rotation"]["@Z"]), om.MEulerRotation.kXYZ, ), om.MSpace.kTransform, )
def angleCompute( self , axeDir , oTrs , baseTrs , trs ): axeDirSkip = [ [ 0 , 1 , 1 ] , [ 1 , 0 , 1 ] , [ 1 , 1 , 0 ] ] # vINIT way = 1 if( 2 < axeDir ): axeDir -= 3 way = -1 vBaseInitValue = [0,0,0] vBaseInitValue[axeDir] = way vBaseInit = ompy.MVector( vBaseInitValue[0] , vBaseInitValue[1] , vBaseInitValue[2] ) # INVERSE ROTATION ORIGINE eulerInit = ompy.MEulerRotation( math.radians(oTrs[3]) , math.radians(oTrs[4]) , math.radians(oTrs[5]) ) eulerInit.invertIt() # vTARGET vTarget = ompy.MVector( trs[0] - oTrs[0] , trs[1] - oTrs[1] , trs[2] - oTrs[2] ) vTarget = vTarget.rotateBy(eulerInit) # ANGLE BASE TARGET rotQuat = ompy.MQuaternion( vBaseInit , vTarget ) rotEuler = rotQuat.asEulerRotation() # ANGLE SKIP AXE angleOut = [ rotEuler.x * axeDirSkip[axeDir][0] , rotEuler.y * axeDirSkip[axeDir][1] , rotEuler.z * axeDirSkip[axeDir][2] ] # ANGLE OUT angleOut = [ math.degrees(angleOut[0]) , math.degrees(angleOut[1]) , math.degrees(angleOut[2]) ] return angleOut
def change(self, diff): if self.originalRotation is None: return if self.index == 0: diffRotation = om.MEulerRotation(diff, 0, 0) elif self.index == 1: diffRotation = om.MEulerRotation(0, diff, 0) elif self.index == 2: diffRotation = om.MEulerRotation(0, 0, diff) else: diffRotation = om.MEulerRotation(0, 0, 0) self.newRotation = self.originalRotation + diffRotation objectXform = om.MFnTransform(self.dagPath) objectXform.setRotation(self.newRotation, om.MSpace.kTransform)
def asEuler(rotation): """Converts tuple(float3) into a MEulerRotation :param rotation: a tuple of 3 elements in degrees which will be converted to redians for the eulerRotation :type rotation: tuple(float) :rtype: MEulerRotation """ return om2.MEulerRotation( [om2.MAngle(i, om2.MAngle.kDegrees).asRadians() for i in rotation])
def getMatrices(node): nodeName = OpenMaya.MFnDagNode(node).getPath() r = cmds.getAttr('{0}.r'.format(nodeName)) r = [math.radians(x) for x in r[0]] ra = cmds.getAttr('{0}.ra'.format(nodeName)) ra = [math.radians(x) for x in ra[0]] jo = cmds.getAttr('{0}.jo'.format(nodeName)) jo = [math.radians(x) for x in jo[0]] wm = OpenMaya.MMatrix(cmds.getAttr('{0}.wm'.format(nodeName))) pm = OpenMaya.MMatrix(cmds.getAttr('{0}.pm'.format(nodeName))) r = OpenMaya.MEulerRotation(*r).asMatrix() * pm ra = OpenMaya.MEulerRotation(*ra).asMatrix() * pm jo = OpenMaya.MEulerRotation(*jo).asMatrix() * pm return wm, r, ra, jo
def set_rotation(self, x, y, z): """Set the absolute rotation of the curve shape in euler rotations. :param x: Rotate X :param y: Rotate Y :param z: Rotate Z """ x, y, z = [v * 0.0174533 for v in [x, y, z]] self.transform_matrix.setRotation(OpenMaya.MEulerRotation(x, y, z))
def rotate_by(self, x, y, z, local=True): """Rotate the curve cvs by the given euler rotation values :param x: Rotate X :param y: Rotate Y :param z: Rotate Z :param local: True for local space, False for world """ x, y, z = [v * 0.0174533 for v in [x, y, z]] space = OpenMaya.MSpace.kObject if local else OpenMaya.MSpace.kWorld self.transform_matrix.rotateBy(OpenMaya.MEulerRotation(x, y, z), space)
def setMayaRotation(aMayaItem, r): '''Set the rotation (XYZ) on the argument Maya scene item.''' aMayaPath = aMayaItem.path() aMayaPathStr = ufe.PathString.string(aMayaPath) aDagPath = om.MSelectionList().add(aMayaPathStr).getDagPath(0) aFn = om.MFnTransform(aDagPath) rads = [radians(v) for v in r] rot = om.MEulerRotation(rads[0], rads[1], rads[2]) aFn.setRotation(rot, om.MSpace.kTransform) return (aMayaPath, aMayaPathStr, aFn, aFn.transformation().asMatrix())
def euler_to_quat(eulers, transforms): """Convert a list of eulers to quaternions :param eulers: List of tuples or lists of length 3 :param transforms: List of transforms per rotation :return: List of quaternions """ quats = [] for i, v in enumerate(eulers): rotate_order = cmds.getAttr("{}.ro".format(transforms[i])) r = [math.radians(x) for x in v] euler = OpenMaya.MEulerRotation(r[0], r[1], r[2], rotate_order) q = euler.asQuaternion() if cmds.nodeType(transforms[i]) == "joint": jo = cmds.getAttr("{}.jo".format(transforms[i]))[0] jo = [math.radians(x) for x in jo] jo = OpenMaya.MEulerRotation(jo[0], jo[1], jo[2]) q *= jo.asQuaternion() quats.append([q.x, q.y, q.z, q.w]) return quats
def mirrorJoint(node, parent, translate, rotate): nFn = om2.MFnDependencyNode(node) rotateOrder = nFn.findPlug("rotateOrder", False).asInt() transMatRotateOrder = generic.intToMTransformRotationOrder(rotateOrder) translation, rotMatrix = mirrorTransform(node, parent, translate, rotate) # MVector, MMatrix jointOrder = om2.MEulerRotation(plugs.getPlugValue(nFn.findPlug("jointOrient", False))) # deal with joint orient jo = om2.MTransformationMatrix().setRotation(jointOrder).asMatrixInverse() # applyRotation and translation rot = mayamath.toEulerFactory(rotMatrix * jo, transMatRotateOrder) setRotation(node, rot) setTranslation(node, translation)
def toEulerZYX(rotMatrix, degrees=False): rotZX = rotMatrix[8] y = math.asin(rotZX) cosY = math.cos(y) x = math.atan2(-rotMatrix[9] * cosY, rotMatrix[10] * cosY) z = math.atan2(-rotMatrix[4] * cosY, rotMatrix[0] * cosY) angles = x, y, z if degrees: return map(math.degrees, angles) return om2.MEulerRotation(angles)
def toEulerZXY(rotMatrix, degrees=False): rotZY = rotMatrix[9] x = -math.asin(rotZY) cosX = math.cos(x) z = math.atan2(rotMatrix[1] * cosX, rotMatrix[5] * cosX) y = math.atan2(rotMatrix[8] * cosX, rotMatrix[10] * cosX) angles = x, y, z if degrees: return map(math.degrees, angles) return om2.MEulerRotation(angles)
def toEulerYZX(rotMatrix, degrees=False): rotYX = rotMatrix[4] z = -math.asin(rotYX) cosZ = math.cos(z) x = math.atan2(rotMatrix[6] * cosZ, rotMatrix[5] * cosZ) y = math.atan2(rotMatrix[8] * cosZ, rotMatrix[0] * cosZ) angles = x, y, z if degrees: return map(math.degrees, angles) return om2.MEulerRotation(angles)
def toEulerYXZ(rotMatrix, degrees=False): rotZ = rotMatrix[6] x = math.asin(rotZ) cosX = math.cos(x) y = math.atan2(-rotMatrix[2] * cosX, rotMatrix[10] * cosX) z = math.atan2(-rotMatrix[4] * cosX, rotMatrix[5] * cosX) angles = x, y, z if degrees: return map(math.degrees, angles) return om2.MEulerRotation(angles)
def toEulerXZY(rotMatrix, degrees=False): rotYY = rotMatrix[1] z = math.asin(rotYY) cosZ = math.cos(z) x = math.atan2(-rotMatrix[9] * cosZ, rotMatrix[5] * cosZ) y = math.atan2(-rotMatrix[2] * cosZ, rotMatrix[0] * cosZ) angles = x, y, z if degrees: return map(math.degrees, angles) return om2.MEulerRotation(angles)
def test_create_twist_composition_at_p5_non_inverted(self): st.create_swing_twist(self.start_joint, self.twist_joint, twist_weight=0.5) cmds.setAttr("{}.rx".format(self.start_joint), 45) m = self.local_matrix() tm = OpenMaya.MTransformationMatrix() tm.rotateBy( OpenMaya.MEulerRotation(math.radians(22.5), 0, 0), OpenMaya.MSpace.kTransform, ) tm.translateBy(OpenMaya.MVector(self.tx, 0, 0), OpenMaya.MSpace.kTransform) self.assertListAlmostEqual(m, tm.asMatrix())
def apply_euler_filter_to_transformed_data(transformed_data, frames, rotation_order='xyz'): """Apply filter to fix channel flipping on euler rotations. This function changes the values of the given transformed_data dictionary. Args: transformed_data(dict): data off all transforms along given frames. frames(list): list of frames to iterate, in ascending order. rotation_order(str): rotation order of the object to apply filter on. """ euler_data = {} for frame in frames: if (frame - 1) not in transformed_data: continue current_rotation = transformed_data[frame]['r'] previous_rotation = transformed_data[frame - 1]['r'] # apply basic flipping filter for 180 degree flips on one channel new_rotation = OpenMaya.MEulerRotation() new_rotation.x = account_for_flip(previous_rotation.x, current_rotation.x) new_rotation.y = account_for_flip(previous_rotation.y, current_rotation.y) new_rotation.z = account_for_flip(previous_rotation.z, current_rotation.z) # apply flipping filter for multi channel flipping result_rotation = flip_euler(new_rotation, rotation_order) result_rotation.x = account_for_flip(previous_rotation.x, result_rotation.x) result_rotation.y = account_for_flip(previous_rotation.y, result_rotation.y) result_rotation.z = account_for_flip(previous_rotation.z, result_rotation.z) # apply the filter based on which value has a smaller distance # from the original rotation. new_rotation_distance = euler_rotation_distance( previous_rotation, new_rotation) result_rotation_distance = euler_rotation_distance( previous_rotation, result_rotation) if result_rotation_distance < new_rotation_distance: new_rotation = result_rotation transformed_data[frame]['r'] = new_rotation
def setRotation(self, vector, radians = False): """ Set rotation. Set radians = True to set it in randians. Parameters: vector (Tuple(x,y,z) or MVector) space (Space.CONSTANT) Default Space.WORLD: Space.LOCAL, Space.WORLD, SpaceTRANSFORM""" if radians == False: rotation = self.vectorDegreesToRadians(vector) eulerAngle = om.MEulerRotation(rotation, RotOrder.XYZ) self._fnTransform.setRotation(eulerAngle.asQuaternion(), Space.WORLD)
def runMultiSelectTestRotate(self, items, expected): '''Engine method to run multiple selection rotate test.''' # Save the initial positions to the memento list. self.multiSelectSnapShotAndTest(items, expected) # Do some rotate commands, and compare with expected. for x, y, z in [[10, 20, 30], [-30, -20, -10]]: cmds.rotate(x, y, z, relative=True, objectSpace=True, forceOrderXYZ=True) # Just as in default rotations by manipulator expected = multiSelectAddRotations(expected, om.MEulerRotation(radians(x), radians(y), radians(z))) self.multiSelectSnapShotAndTest(items, expected) # Test undo, redo. self.multiSelectRewindMemento(items) self.multiSelectFforwardMemento(items)