Ejemplo n.º 1
0
def build(
    surface=None,
    ref_xforms=None,
    up_xform=None,
    num_controls=3,
    num_follicles=10,
    control_scheme="fk",
    name={"name": "ribbon"},
    spansUV=[1, 4],
    scale=1.0,
    baseRig="auto",
    parent=None,
):
    """ Takes two points or a given surface and creates a ribbon module based on that.
    Args:
        surface (pm.nt.nurbsCurve): nurbs curve to generate things on
        ref_xforms [pm.nt.Transform]: the two points to make a ribbon between
        num_controls (int): number of controls to be generated
        num_follicles (int): number of follicles (and resulting joints) to be generated
    Returns list(grp, list(joints))
    Usage:
        build(ref_xforms=[pm.PyNode('locator1'),pm.PyNode('locator2')], up_xform=pm.PyNode('locator3'), num_follicles=12, num_controls=2, name="path", control_scheme='ik')
    @param baseRig: instance of core.module.Base class
    @return: dictionary with rig module objects
    """
    with pm.UndoChunk():
        # make rig module
        namer.set(name)
        namer.type.set("group")
        rigmodule = module.Module(name=namer.get_dict(), baseObj=baseRig)

        mesh_grp = pm.group(n=namer.get(childType="mesh"), em=True, p=rigmodule.partsGrp)
        ribbon_grp = pm.group(n=namer.get(childType="ribbons"), em=True, p=rigmodule.partsGrp)
        fol_grp = pm.group(n=namer.get(childType="follicles"), em=True, p=rigmodule.partsGrp)

        # TODO: Should be able to pass namer classes in case you want to override the default namer
        drive_skeleton_grp = pm.group(
            em=True, n=namer.get(purpose="drive", childType="skeleton"), p=rigmodule.jointsGrp
        )
        skin_skeleton_grp = pm.group(em=True, n=namer.get(purpose="skin", childType="skeleton"), p=rigmodule.jointsGrp)

        # Now on to the good stuff.
        xformA, xformB = ref_xforms

        # First create follicles and ribbon
        ribbon = mesh_factory.build_nurbs_between_points(xformA, xformB, up_xform, spansUV=spansUV)
        ribbon.rename(namer.get(type="nurbs", purpose="ribbon"))
        ribbon.setParent(mesh_grp)

        follicles = []
        spacing = 1.0 / (num_follicles - 1)
        for fol_index in range(0, num_follicles):
            follicles.append(
                follicle_factory.build(
                    ribbon,
                    0.5,
                    fol_index * spacing,
                    name=namer.get_dict(var=namer.get_alpha(fol_index)),
                    scale=scale,
                    parent=fol_grp,
                )
            )

        # Then create x many controls between pointA and pointB
        control_positions = mesh_factory.get_positions_along_mesh_UV(ribbon, num_controls, u_override=0.5, dir="v")

        controls = control_factory.build_control_chain(
            control_positions,
            chain_type=control_scheme,
            name=namer.get_dict(),
            scale=scale,
            parent=rigmodule.priControlsGrp,
            shape="sphere",
            lockChannels=["s", "v"],
        )

        controls = [control.C for control in controls]

        # Then create the offset grouped joints on each follicle and connect the offset groups movements to the follicles
        namer.reset(name)
        drive_joints = joint_factory.build_from_points(
            controls, name=namer.get_dict(purpose="drive"), chain=True, parent=drive_skeleton_grp
        )
        skin_joints = joint_factory.build_from_points(
            follicles, name=namer.get_dict(purpose="skin"), parent=skin_skeleton_grp, offset=True
        )

        # Need to unparent the control joints in order to skin them and then reparent
        joint_parents = {}
        for joint in drive_joints:
            joint_parents[joint] = joint.getParent()
            joint.setParent(w=True)

        pm.skinCluster(drive_joints, ribbon)

        for joint in joint_parents:
            joint.setParent(joint_parents[joint], a=True)
        del (joint_parents)
        # Connect the controls to the drive joints
        for control, drive_joint in zip(controls, drive_joints):
            pm.parentConstraint(control, drive_joint, mo=True)

        # Connect the skin joints to the follicle positions with offset groups
        for skin_joint, follicle in zip(skin_joints, follicles):
            follicle.translate.connect(skin_joint.getParent().translate)
            follicle.rotate.connect(skin_joint.getParent().rotate)

        # Profit!
        """
Ejemplo n.º 2
0
def build(
          curve,
          aim_curve,
          num_joints = 0,
          prefix = 'splineIKTwist',
          rebuild = True,
          scale = 1.0,
          constrain_object = None,
          mo = True,
          aimVector = (0,1,0),
          upVector = (1,0,0),
          worldUpType = 'object', #objectUp
          baseRig = 'auto',
          parent = None
          ):
    """Takes two curves, creates joints on the first and aims objects at the second.
    Args:
        aim_curve (pm.nt.nurbsCurve): nurbs curve to generate things on
        aimCrv (pm.nt.nurbsCurve): nurbs curve to aim things to
        num_jnts (int): number of joints to be generated
        other : all of the aim vector constraint settings
    Returns list(grp, list(joints))
    Usage:
        build(pm.ls(sl=True)[0], pm.ls(sl=True)[1], num_joints=20, prefix="path")

    @param curves: [pm.nt.Transform], list of transforms with curve shape nodes
    @param target_surface: pm.nt.Transform, transform with a shape node
    @param prefix: str, prefix to name new objects
    @param snapToSurface: int, snap to surface or not (0,1)
    @param scale: float, scale factor for size of controls
    @param baseRig: instance of core.module.Base class
    @return: dictionary with rig module objects
    """
    # make rig module
    namer.name.set(prefix)
    namer.type.set('group')
    rigmodule = module.Module( prefix = prefix, baseObj = baseRig )
    
    mesh_grp = pm.group(n=namer.get(purpose='mesh'), em=True, p=rigmodule.partsGrp)
    aim_grp = pm.group(n=namer.get(purpose='aimdriver'), em=True, p=rigmodule.partsGrp)
    clstr_grp = pm.group(n=namer.get(childType='clusters'), em=True, p=rigmodule.partsGrp)
    crv_grp = pm.group(n=namer.get(childType='curves'), em=True, p=rigmodule.partsGrp)
    
    # TODO: Should be able to pass namer classes in case you want to override the default namer
    drive_skeleton_grp = pm.group(em=True,
                                  n=namer.get(purpose='drive', childType='skeleton'),
                                  p=rigmodule.jointsGrp)
    ik_skeleton_grp = pm.group(em=True,
                               n=namer.get(purpose='ik', childType='skeleton'),
                               p=rigmodule.jointsGrp)
    
    # Actual creation of joints
    joints = joint_factory.make_joints_along_curve(curve,
                                                   num_joints=num_joints,
                                                   prefix=prefix,
                                                   rebuild=rebuild)
    
    ikJoints = joint_factory.make_joints_along_curve(curve, 
                                                     num_joints=num_joints,
                                                     prefix=prefix+'IK',
                                                     rebuild=rebuild)
    
    # Getting names of next parts of the puzzle
    locator_names = namer.get_chain(num_joints, var='A', type='locator', name=prefix, purpose='aimdrv')
    poci_names = namer.get_chain(num_joints, var='A', type='poci', name=prefix, purpose='aimdrv')
    
    index = 0
    # How do we get the names after the fact...
    for joint, ikJoint, loc_name, poci_name in zip(joints, ikJoints, locator_names, poci_names):
        joint.displayLocalAxis.set(1)
        #print joint, ikJoint, loc_name, poci_name
        # poci = pointOnCurveInfo
        joint.setParent(drive_skeleton_grp)
        poci_orig, cpoc, pc = curve_factory.get_closest_point_and_position_on_curve(joint, curve)
        
        # extra point on curve info for the aim curve to have parallel
        poci = pm.nodetypes.PointOnCurveInfo(n=poci_name)
        #poci.turnOnPercentage.set(1)
        aim_curve.getShape().attr("worldSpace[0]").connect(poci.inputCurve)
        poci_orig.parameter.connect(poci.parameter)
        
        # aim curve locator for look up
        loc = pm.spaceLocator(n=loc_name)
        loc.setParent(aim_grp)
        poci.position.connect(loc.t)
        
        pc = pm.pointConstraint(ikJoint, joint, mo=True)
        
        
        # make sure the joints aim down chain
        if index != len(joints)-1:
            next_joint = ikJoints[index+1]
            ac = pm.aimConstraint(loc, joint,
                              mo=mo,
                              aimVector=aimVector,
                              upVector=upVector,
                              worldUpType=worldUpType,
                              worldUpObject=next_joint.name()
                              )
        else:
            ac = pm.aimConstraint(loc, joint,
                                  mo=mo,
                                  aimVector=aimVector,
                                  upVector=upVector)
        
        
        index+=1
        
    ikHandle = pm.ikHandle(sj=ikJoints[0], ee=ikJoints[-1],
                           sol='ikSplineSolver', c=curve, ccv=False, rtm=False)[0]
    
    # Now setup the clusters
    base_clusters = curve_factory.cluster_curve(curve, prefix='baseClstr', ends=True)
    offset_clusters = curve_factory.cluster_curve(aim_curve, prefix='aimClstr', ends=True)

    for b_clstr, o_clstr in zip(base_clusters, offset_clusters):
        pm.parentConstraint(b_clstr[1], o_clstr[1], mo=True)
        o_clstr[1].visibility.set(0)
        b_clstr[1].setParent(clstr_grp)
        o_clstr[1].setParent(clstr_grp)

    # And finally clean up the grouping/vis
    ikJoints[0].setParent(ik_skeleton_grp)
    curve.setParent(crv_grp)
    aim_curve.setParent(crv_grp)
    ikHandle.setParent(ik_skeleton_grp)
    aim_grp.inheritsTransform.set(0)
    
    #ik_skeleton_grp.visibility.set(0)
    #crv_grp.visibility.set(0)
    
    return rigmodule