Exemplo n.º 1
0
def decompose_matrix(tfm_matrix, prv_rot):
    """
    Decompose a MTransformationMatrix into transform attributes.

    .. note::
        It is assumed the given matrix is already re-ordered into the
        desired rotation order.

    :param tfm_matrix: Transform matrix to be decomposed.
    :type tfm_matrix: maya.api.OpenMaya.MTransformationMatrix

    :param prv_rot: The previous rotation values (on the previous frame).
    :type prv_rot: (float, float, float) or None

    :returns: Tuple of 9 values: TX, TY, TZ, RX, RY, RZ, SX, SY and SZ.
    :rtype: (float, float, float, float, float, float, float, float, float)
    """
    space = OpenMaya2.MSpace.kWorld

    # Decompose matrix into components
    trans = tfm_matrix.translation(space)
    scl = tfm_matrix.scale(space)
    rot = tfm_matrix.rotation(asQuaternion=False)

    # Convert and clean rotation values
    trans = (trans[0], trans[1], trans[2])
    scl = (scl[0], scl[1], scl[2])
    rot = (math.degrees(rot[0]), math.degrees(rot[1]), math.degrees(rot[2]))
    if prv_rot is not None:
        rot = (animcurve_utils.euler_filter_value(prv_rot[0], rot[0]),
               animcurve_utils.euler_filter_value(prv_rot[1], rot[1]),
               animcurve_utils.euler_filter_value(prv_rot[2], rot[2]))
    prv_rot = rot

    return tuple(trans + rot + scl)
Exemplo n.º 2
0
def set_transform_values(tfm_matrix_cache,
                         times,
                         src_tfm_node,
                         dst_tfm_node,
                         rotate_order=None,
                         delete_static_anim_curves=False,
                         eval_mode=None):
    """
    Set transform node values on a destination node at times,
    using previously evaluated cached values.

    src_tfm_node is used to look-up into the cache for values.
    dst_tfm_node is the node that will be set values on. It is
    possible to have src_tfm_node and dst_tfm_node reference the same
    Maya node, or even the same object.

    .. note::
       The function assumes the given destination node has no locked
       attributes.

    :param tfm_matrix_cache: A cache holding queried matrix values.
    :type tfm_matrix_cache: TransformMatrixCache

    :param times: The times to set transforms values on.
    :type times: [int or float, ...]

    :param src_tfm_node: Source node to get cached transform values from.
    :type src_tfm_node: TransformNode

    :param dst_tfm_node: Destination node set transform values on.
    :type dst_tfm_node: TransformNode

    :param rotate_order: The rotation order to set on the dst_node,
                         or use the existing rotation on the dst_node
                         if rotate_order is None.
    :type rotate_order: str

    :param delete_static_anim_curves: If an animation curve is static,
                                      it will be deleted.
    :type delete_static_anim_curves: bool

    :param eval_mode: What type of evaluation method to use?
    :type eval_mode: mmSolver.utils.constant.EVAL_MODE_*

    :rtype: None
    """
    assert isinstance(tfm_matrix_cache, TransformMatrixCache)
    assert isinstance(times, (list, tuple))
    assert isinstance(src_tfm_node, TransformNode)
    assert isinstance(dst_tfm_node, TransformNode)
    assert rotate_order is None or isinstance(rotate_order, (str, unicode))
    if eval_mode is None:
        eval_mode = const.EVAL_MODE_DEFAULT
    assert eval_mode in const.EVAL_MODE_LIST

    current_frame = maya.cmds.currentTime(query=True)
    space = OpenMaya2.MSpace.kWorld
    attrs = [
        'translateX', 'translateY', 'translateZ', 'rotateX', 'rotateY',
        'rotateZ', 'scaleX', 'scaleY', 'scaleZ'
    ]

    dst_node = dst_tfm_node.get_node()
    if rotate_order is None:
        rotate_order = maya.cmds.xform(dst_node, query=True, rotateOrder=True)
    else:
        maya.cmds.xform(dst_node, edit=True, rotateOrder=rotate_order)
    assert rotate_order in const.ROTATE_ORDER_STR_LIST
    rotate_order_api = ROTATE_ORDER_STR_TO_APITWO_CONSTANT[rotate_order]

    # Get destination node plug.
    dst_node = dst_tfm_node.get_node()
    dst_name = dst_node + '.parentInverseMatrix[0]'
    parent_inv_matrix_plug = node_utils.get_as_plug_apitwo(dst_name)

    # Query the matrix of nodes.
    world_mat_list = get_transform_matrix_list(tfm_matrix_cache,
                                               times,
                                               src_tfm_node,
                                               rotate_order=rotate_order)
    assert len(world_mat_list) == len(times)

    # Set transform
    dst_node = dst_tfm_node.get_node()
    prv_rot = None
    for t, world_mat in zip(times, world_mat_list):
        assert t is not None
        assert world_mat is not None

        parent_inv_mat = None
        if eval_mode == const.EVAL_MODE_API_DG_CONTEXT:
            ctx = create_dg_context_apitwo(t)
            parent_inv_mat = get_matrix_from_plug_apitwo(
                parent_inv_matrix_plug, ctx)
        elif eval_mode == const.EVAL_MODE_TIME_SWITCH_GET_ATTR:
            maya.cmds.currentTime(t, update=True)
            plug_name = parent_inv_matrix_plug.name()
            parent_inv_mat = maya.cmds.getAttr(plug_name)
            parent_inv_mat = OpenMaya2.MMatrix(parent_inv_mat)
        else:
            msg = 'eval_mode does not have a valid value'
            raise ValueError(msg % eval_mode)

        local_mat = world_mat.asMatrix() * parent_inv_mat
        local_mat = OpenMaya2.MTransformationMatrix(local_mat)
        local_mat.reorderRotation(rotate_order_api)

        # Decompose matrix into components
        trans = local_mat.translation(space)
        scl = local_mat.scale(space)
        rot = local_mat.rotation(asQuaternion=False)

        # Convert and clean rotation values
        trans = (trans[0], trans[1], trans[2])
        scl = (scl[0], scl[1], scl[2])
        rot = (math.degrees(rot[0]), math.degrees(rot[1]),
               math.degrees(rot[2]))
        if prv_rot is not None:
            rot = (animcurve_utils.euler_filter_value(prv_rot[0], rot[0]),
                   animcurve_utils.euler_filter_value(prv_rot[1], rot[1]),
                   animcurve_utils.euler_filter_value(prv_rot[2], rot[2]))
        prv_rot = rot

        # Set Keyframes
        values = trans + rot + scl
        assert len(attrs) == len(values)
        for attr, v in zip(attrs, values):
            maya.cmds.setKeyframe(dst_node, attribute=attr, time=t, value=v)

    if delete_static_anim_curves is True:
        maya.cmds.delete(dst_node, staticChannels=True)

    if eval_mode == const.EVAL_MODE_TIME_SWITCH_GET_ATTR:
        maya.cmds.currentTime(current_frame, update=True)
    return
Exemplo n.º 3
0
def set_transform_values(tfm_matrix_cache,
                         times,
                         src_tfm_node,
                         dst_tfm_node,
                         rotate_order=None,
                         delete_static_anim_curves=True):
    """
    Set transform node values on a destination node at times,
    using previously evaluated cached values.

    src_tfm_node is used to look-up into the cache for values.
    dst_tfm_node is the node that will be set values on. It is
    possible to have src_tfm_node and dst_tfm_node reference the same
    Maya node, or even the same object.

    .. note::
       The function assumes the given destination node has no locked
       attributes.

    :param tfm_matrix_cache: A cache holding queried matrix values.
    :type tfm_matrix_cache: TransformMatrixCache

    :param times: The times to set transforms values on.
    :type times: [int or float, ...]

    :param src_tfm_node: Source node to get cached transform values from.
    :type src_tfm_node: TransformNode

    :param dst_tfm_node: Destination node set transform values on.
    :type dst_tfm_node: TransformNode

    :param rotate_order: The rotation order to set on the dst_node,
                         or use the existing rotation on the dst_node
                         if rotate_order is None.
    :type rotate_order: str

    :param delete_static_anim_curves: If an animation curve is static,
                                      it will be deleted.
    :type delete_static_anim_curves: bool

    :rtype: None
    """
    assert isinstance(tfm_matrix_cache, TransformMatrixCache)
    assert isinstance(times, (list, tuple))
    assert isinstance(src_tfm_node, TransformNode)
    assert isinstance(dst_tfm_node, TransformNode)
    assert rotate_order is None or isinstance(rotate_order, (str, unicode))

    space = OpenMaya2.MSpace.kWorld
    attrs = [
        'translateX', 'translateY', 'translateZ',
        'rotateX', 'rotateY', 'rotateZ',
        'scaleX', 'scaleY', 'scaleZ'
    ]

    dst_node = dst_tfm_node.get_node()
    if rotate_order is None:
        rotate_order = maya.cmds.xform(
            dst_node,
            query=True,
            rotateOrder=True)
    else:
        maya.cmds.xform(
            dst_node,
            edit=True,
            rotateOrder=rotate_order)
    assert rotate_order in const.ROTATE_ORDER_STR_LIST
    rotate_order = ROTATE_ORDER_STR_TO_APITWO_CONSTANT[rotate_order]

    # Get destination node plug.
    src_node = src_tfm_node.get_node()
    src_name = src_node + '.parentInverseMatrix[0]'
    parent_inv_matrix_plug = node_utils.get_as_plug_apitwo(src_name)

    # Query the matrix node.
    src_node_uuid = src_tfm_node.get_node_uuid()
    src_node_attrs = tfm_matrix_cache.get_attrs_for_node(src_node_uuid)
    with_pivot = len(src_node_attrs) > 1
    world_mat_list = []
    if with_pivot is False:
        world_mat_list = tfm_matrix_cache.get_node_attr_matrix(
            src_node_uuid,
            'worldMatrix[0]',
            times,
        )
    else:
        mat_list = tfm_matrix_cache.get_node_attr_matrix(
            src_node_uuid,
            'matrix',
            times,
        )
        assert len(mat_list) == len(times)

        par_inv_mat_list = tfm_matrix_cache.get_node_attr_matrix(
            src_node_uuid,
            'parentInverseMatrix[0]',
            times,
        )
        assert len(par_inv_mat_list) == len(times)

        rot_piv_x_list = tfm_matrix_cache.get_node_attr_matrix(
            src_node_uuid,
            'rotatePivotX',
            times,
        )
        assert len(rot_piv_x_list) == len(times)

        rot_piv_y_list = tfm_matrix_cache.get_node_attr_matrix(
            src_node_uuid,
            'rotatePivotY',
            times,
        )
        assert len(rot_piv_y_list) == len(times)

        rot_piv_z_list = tfm_matrix_cache.get_node_attr_matrix(
            src_node_uuid,
            'rotatePivotZ',
            times,
        )
        assert len(rot_piv_z_list) == len(times)

        # Reconstruct World-Matrix, accounting for pivot point.
        space = OpenMaya2.MSpace.kWorld
        loop_iter = zip(mat_list,
                        par_inv_mat_list,
                        rot_piv_x_list,
                        rot_piv_y_list,
                        rot_piv_z_list)
        for mat, par_inv_mat, rot_piv_x, rot_piv_y, rot_piv_z in loop_iter:
            assert mat is not None
            assert par_inv_mat is not None
            assert rot_piv_x is not None
            assert rot_piv_y is not None
            assert rot_piv_z is not None
            mat = OpenMaya2.MTransformationMatrix(mat)
            pivot = OpenMaya2.MVector(rot_piv_x, rot_piv_y, rot_piv_z)
            trans = mat.translation(space)
            mat.setTranslation(trans + pivot, space)
            mat = mat.asMatrix()
            world_mat = par_inv_mat * mat
            world_mat_list.append(world_mat)
    assert len(world_mat_list) == len(times)

    # Set transform
    dst_node = dst_tfm_node.get_node()
    prv_rot = None
    for t, world_mat in zip(times, world_mat_list):
        assert world_mat is not None
        ctx = create_dg_context_apitwo(t)
        parent_mat = get_matrix_from_plug_apitwo(
            parent_inv_matrix_plug,
            ctx
        )

        local_mat = parent_mat * world_mat
        local_mat = OpenMaya2.MTransformationMatrix(local_mat)
        local_mat.reorderRotation(rotate_order)

        # Decompose matrix into components
        trans = local_mat.translation(space)
        scl = local_mat.scale(space)
        rot = local_mat.rotation(asQuaternion=False)

        # Convert and clean rotation values
        trans = (trans[0], trans[1], trans[2])
        scl = (scl[0], scl[1], scl[2])
        rot = (
            math.degrees(rot[0]),
            math.degrees(rot[1]),
            math.degrees(rot[2])
        )
        if prv_rot is not None:
            rot = (
                animcurve_utils.euler_filter_value(prv_rot[0], rot[0]),
                animcurve_utils.euler_filter_value(prv_rot[1], rot[1]),
                animcurve_utils.euler_filter_value(prv_rot[2], rot[2])
            )
        prv_rot = rot

        # Set Keyframes
        values = trans + rot + scl
        assert len(attrs) == len(values)
        for attr, v in zip(attrs, values):
            maya.cmds.setKeyframe(dst_node, attribute=attr, time=t, value=v)

    if delete_static_anim_curves is True:
        maya.cmds.delete(dst_node, staticChannels=True)
    return