Ejemplo n.º 1
0
def getMatrixFromVector(forward, up=None, forward_axis='z', location=None):
    """
    Creates a rotation from given forward direction and up direction. Which is then used to calculate a matrix.

    Args:
        forward (Any): Vector that faces forward.

        up (Any): Vector that faces up. If none given will use scene up axis.

        forward_axis (string): What local vector will face forward in the matrix.

        location (Any): Where the matrix should be in world space. If none given, will be at origin.

    Returns:
        (pm.nodetypes.Matrix): Matrix calculated from given forward vector.
    """
    scene_up = pm.upAxis(axis=True, q=True)
    scene_up = convert.axisToVector(scene_up)
    up = convert.toVector(up, invalid_default=scene_up)

    right = forward.cross(up).normal()
    up = right.cross(forward).normal()
    matrix = []

    if forward_axis == 'x':
        matrix = [forward.get(), up.get(), right.get()]
    elif forward_axis == 'y':
        matrix = [up.get(), forward.get(), right.get()]
    elif forward_axis == 'z':
        matrix = [(right * -1).get(), up.get(), forward.get()]

    location = convert.toVector(location, invalid_default=True)
    matrix.append(location)
    return pm.dt.Matrix(*matrix)
Ejemplo n.º 2
0
def orientChainWithUpObjects(transform_start=None,
                             up_start=None,
                             aim=None,
                             up_axis=None):
    """
    Orients the given transforms by aiming the given axis to their child and the up to the respective up transform.

    Args:
        transform_start (pm.nodetypes.Transform): Start of the chain to orient.

        up_start (pm.nodetypes.Transform): Start of the chain that transforms will have their up axis aim at.

        aim (list): Axis vector to aim towards child joint.

        up_axis (list): Axis vector to aim towards the up object.
    """
    if not transform_start:
        transform_start = pm.selected()[0]

    if not up_start:
        up_start = pm.selected()[-1]

    if transform_start == up_start:
        pm.error('Please select more than one transform!')

    aim = convert.toVector(aim, invalid_default=[0, 1, 0])
    up_axis = convert.toVector(up_axis, invalid_default=[1, 0, 0])

    transforms = transform_start.getChildren(ad=True)
    uppers = up_start.getChildren(ad=True)
    transforms.append(transform_start)
    uppers.append(up_start)

    transforms.reverse()
    uppers.reverse()
    pm.parent(transforms, w=True)

    for i, (transform, up) in enumerate(zip(transforms, uppers)):
        if i != 0:
            pm.parent(transform, transforms[i - 1])

        if transform.hasAttr('jointOrient'):
            transform.jointOrient.set((0, 0, 0))

        if transform == transforms[-1]:
            continue

        constraint = pm.aimConstraint(transforms[i + 1],
                                      transform,
                                      aim=aim,
                                      u=up_axis,
                                      wuo=up,
                                      mo=False,
                                      wut='object')
        pm.delete(constraint)
Ejemplo n.º 3
0
def orientChain(start=None, end=None, aim=None, up=None, world_up=None):
    """
    Orients the chain starting from given start and ending at given end to aim at the child joint with the
    given aim axis.

    Args:
        start (pm.nodetypes.Transform): Top parent of the chain.

        end (pm.nodetypes.Transform): The child to end search at. If none given, will return only the given start.

        aim (list): Axis to aim at

        up (list): Axis to aim at the given world direction.

        world_up (list): Axis up will try to aim at.
    """
    if not start:
        start = pm.selected()[0]

    if not end:
        end = pm.selected()[-1]

    if start == end:
        pm.error('Please select more than one transform!')

    transforms = getChain(start, end)
    first_parent = transforms[0].getParent()

    aim = convert.toVector(aim, invalid_default=[1, 0, 0])
    up = convert.toVector(up, invalid_default=[1, 0, 0])
    world_up = convert.toVector(world_up, invalid_default=[1, 0, 0])

    pm.parent(transforms, w=True)
    for i, transform in enumerate(transforms):

        if i == 0:
            if first_parent:
                pm.parent(transform, first_parent)
        else:
            pm.parent(transform, transforms[i - 1])

        if transform.hasAttr('jointOrient'):
            transform.jointOrient.set((0, 0, 0))

        if transform == transforms[-1]:
            continue

        constraint = pm.aimConstraint(transforms[i + 1],
                                      transform,
                                      aim=aim,
                                      u=up,
                                      wu=world_up,
                                      mo=False,
                                      wut='vector')
        pm.delete(constraint)
Ejemplo n.º 4
0
def getDirection(start, end):
    """
    Gets the vector direction aiming between the given start and end.

    Args:
        start (Any): Transform or vector where direction should start from.

        end (Any): Transform or vector where direction should end/aim at.

    Returns:
        (pm.dt.Vector): Direction aiming from start to end normalized.
    """
    start_location = convert.toVector(start)
    end_location = convert.toVector(end)
    aim_direction = (end_location - start_location).normal()
    return aim_direction
Ejemplo n.º 5
0
def getDistance(start, end):
    """
    Gets the distance between given start and end.

    Args:
        start (Any): Start point to get distance to end.

        end (Any): End point to get distance from end.

    Returns:
        (float): Distance from start point to end point.
    """
    start_location = convert.toVector(start)
    end_location = convert.toVector(end)

    return (end_location - start_location).length()
Ejemplo n.º 6
0
def calculatePoleVector(start_transform, mid_transform, end_transform, scale=1, forward=[0, 0, 1]):
    """
    Props to Greg Hendrix for walking through the math: https://vimeo.com/240328348

    Args:
        start_transform (PyNode): Start of the joint chain

        mid_transform (PyNode): Mid joint of the chain.

        end_transform (PyNode): End joint of the chain.

        scale (float): How far away should the pole vector position be compared to the chain length.

        forward (Any): Node or list to convert to vector direction to move pole vector if chain is in straight line.

    Returns:
        (list): Transform of pole vector control. Translation as first index, rotation as second, scale as third.
    """
    is_in_straight_line = False
    zero_vector = pm.dt.Vector(0, 0, 0)

    # if transform has rotations or joint orient, then its not in a straight line and we can figure out pole vector
    if mid_transform.r.get().isEquivalent(zero_vector, tol=0.5):
        if mid_transform.hasAttr('orientJoint'):
            if mid_transform.orientJoint.get().isEquivalent(zero_vector, tol=0.5):
                is_in_straight_line = True
        else:
            is_in_straight_line = True

    # if transform is in a straight line use the location of the mid transform to place the pole vector
    if is_in_straight_line:
        translation = pm.dt.Vector(pm.xform(mid_transform, q=True, ws=True, rp=True))
        rotation = pm.xform(mid_transform, q=True, ws=True, ro=True)

        if forward:
            forward = convert.toVector(forward)
            distance = pipermath.getDistance(start_transform, end_transform)
            forward = forward * (distance * scale)
            translation = translation + forward

    else:
        start = pm.dt.Vector(pm.xform(start_transform, q=True, ws=True, rp=True))
        mid = pm.dt.Vector(pm.xform(mid_transform, q=True, ws=True, rp=True))
        end = pm.dt.Vector(pm.xform(end_transform, q=True, ws=True, rp=True))

        start_to_end = end - start
        start_to_mid = mid - start

        start_to_end_length = start_to_end.length()
        mid_scale = start_to_end.dot(start_to_mid) / (start_to_end_length * start_to_end_length)
        mid_chain_point = start + start_to_end * mid_scale

        chain_length = (mid - start).length() + (end - mid).length()
        translation = (mid - mid_chain_point).normal() * chain_length * scale + mid
        rotation = pipermath.getAimRotation(mid_chain_point, translation)

    single_scale = mid_transform.radius.get() if mid_transform.hasAttr('radius') else 1
    scale = [single_scale, single_scale, single_scale]

    return translation, rotation, scale, is_in_straight_line
Ejemplo n.º 7
0
def getMatrixFromVector(forward, up=None, forward_axis='z', location=None):
    """
    Creates a rotation from given forward direction and up direction. Which is then used to calculate a matrix.

    Args:
        forward (Any): Vector that faces forward.

        up (Any): Vector that faces up. If none given will use scene up axis.

        forward_axis (string): What local vector will face forward in the matrix.

        location (Any): Where the matrix should be in world space. If none given, will be at origin.

    Returns:
        (pm.nodetypes.Matrix): Matrix calculated from given forward vector.
    """
    if isinstance(up, (list, tuple)):
        up = pm.dt.Vector(up)
    elif isinstance(up, str):
        up = pm.dt.Vector(convert.axisToVector(up))
    elif isinstance(up, pm.dt.Vector):
        pass
    else:
        up = pm.upAxis(axis=True, q=True)
        up = pm.dt.Vector(convert.axisToVector(up))

    right = forward.cross(up).normal()
    up = right.cross(forward).normal()
    coordinates = []

    if forward_axis == 'x':
        coordinates = [forward.get(), up.get(), right.get()]
    elif forward_axis == 'y':
        coordinates = [up.get(), forward.get(), right.get()]
    elif forward_axis == 'z':
        coordinates = [(right * -1).get(), up.get(), forward.get()]

    location = convert.toVector(location, invalid_zero=True)
    coordinates.append(location)
    return pm.dt.Matrix(*coordinates)