예제 #1
0
def run(params, rig):
    if not cmds.pluginInfo('matrixNodes', q=True, l=True):
        cmds.loadPlugin('matrixNodes')

    follicle = cmds.createNode('follicle')
    follicle_transform = cmds.listRelatives(follicle, p=True)[0]
    cmds.connectAttr('{}.outRotate'.format(follicle), '{}.rotate'.format(follicle_transform))
    cmds.connectAttr('{}.outTranslate'.format(follicle), '{}.translate'.format(follicle_transform))
    cmds.connectAttr('{}.worldMatrix'.format(params['geometry'].name()), '{}.inputWorldMatrix'.format(follicle))

    cmds.parent(follicle_transform, rig['rigGroup'])

    geometry_dag_path = get_dag_path(params['geometry'].name())
    m_point = om2.MPoint(cmds.xform(params['target'].name(), q=True, ws=True, t=True))
    if geometry_dag_path.hasFn(om2.MFn.kTransform):
        dag_path = om2.MFnDagNode(geometry_dag_path).dagPath()
        dag_path.extendToShape(0)
    else:
        dag_path = geometry_dag_path

    if dag_path.hasFn(om2.MFn.kMesh):
        cmds.connectAttr('{}.worldMesh'.format(dag_path.partialPathName()), '{}.inputMesh'.format(follicle))
        param_u_value, param_v_value, face_id = om2.MFnMesh(dag_path).getUVAtPoint(m_point, om2.MSpace.kWorld)
    elif dag_path.hasFn(om2.MFn.kNurbsSurface):
        cmds.connectAttr('{}.worldSpace'.format(dag_path.partialPathName()), '{}.inputSurface'.format(follicle))
        param_u_value, param_v_value = om2.MFnNurbsSurface(dag_path).getParamAtPoint(m_point, om2.MSpace.kWorld)
    else:
        raise ValueError('`geometry` Parameter should be either a Mesh or Nurbs Surface')

    cmds.setAttr('{}.parameterU'.format(follicle), param_u_value)
    cmds.setAttr('{}.parameterV'.format(follicle), param_v_value)

    pc = cmds.parentConstraint(follicle_transform, params['target'].name(), mo=params['maintainOffset'])
    sc = cmds.scaleConstraint(follicle_transform, params['target'].name(), mo=params['maintainOffset'])
    cmds.parent(pc, sc, rig['noXformGroup'])
예제 #2
0
def populate_among_plane(surface, dag, num):
    sel = om.MSelectionList()
    sel.add(surface)

    plane = om.MFnNurbsSurface()
    plane.setObject(sel.getDagPath(0))

    params = np.linspace(0, 1, num)

    new_dags = []
    for par in params:
        new_dag = cmds.duplicate(dag)[0]
        pos = plane.getPointAtParam(0.5, par)
        cmds.xform(new_dag, t=(pos[0], pos[1], pos[2]), ws=True)
        new_dags.append(new_dag)

    for dag in new_dags:
        attach_to_surface(surface, dag, snap=True)
예제 #3
0
def closest_point_on_surface(surface, point):
    ''' find closest point on surface and it's UV values

    Args:
        surface (str): nurbs surface
        point tuple(float, float, float): position to reference
    Return:
         tuple(float, float, float), (int), (int): position, u param, v param
    '''
    sel = om.MSelectionList()
    sel.add(surface)

    plane = om.MFnNurbsSurface()
    plane.setObject(sel.getDagPath(0))

    point = om.MPoint(om.MVector(point))

    pos, parU, parV = plane.closestPoint(point)

    return pos, parU, parV
예제 #4
0
def buildRibbon(start,
                end,
                normal,
                numControls=3,
                name='Ribbon',
                groupName='',
                controlSpec={}):

    chain = util.getChain(start, end)
    controlChain = util.dupChain(start, end)

    if not name:
        name = 'Ribbon'

    container = util.parentGroup(chain[0])
    container.setParent(lib.getNodes.mainGroup())

    world = group(em=True)
    hide(world)
    world.setParent(container)

    #controlChain[0].setParent( container )

    crv = curve(d=1, p=[(0, 0, 0)] * len(chain))

    for i, j in enumerate(chain):
        xform(crv.cv[i], t=xform(j, q=True, ws=True, t=True), ws=True)

    dup = duplicate(crv)[0]

    # &&& Obviously need to calc the offset somehow, maybe I can use the mirror state?  Maybe not, due to asymmetry
    #offset = dt.Vector(5, 0, 0)
    offset = normal

    crv.t.set(offset)
    dup.t.set(offset * -1)

    surfaceTrans = loft(crv,
                        dup,
                        uniform=True,
                        polygon=0,
                        sectionSpans=1,
                        degree=3,
                        autoReverse=True)[0]
    surfaceTrans.setParent(world)

    delete(crv, dup)

    rebuildSurface(surfaceTrans,
                   rebuildType=0,
                   replaceOriginal=True,
                   spansU=1,
                   spansV=(len(chain) - 1) * 2,
                   dir=2,
                   degreeV=3,
                   degreeU=1)
    hide(surfaceTrans)

    surfaceShape = surfaceTrans.getShape()

    closest = createNode('closestPointOnSurface')
    surfaceShape.worldSpace >> closest.inputSurface

    vScalar = surfaceShape.minMaxRangeV.get()[1]

    #constraints = []

    for jnt, hairJoint in zip(chain, controlChain):
        #jnt.setParent(world)

        follicle = createNode('follicle')
        hide(follicle)
        trans = follicle.getParent()

        #hairJoints.append(trans)
        trans.setParent(world)

        pos = jnt.getTranslation(space='world')
        closest.inPosition.set(pos)

        surfaceShape.local >> follicle.inputSurface

        u = closest.parameterU.get()
        # closestPointOnSurface returns val in relation to the maxV but the follicle needs it normalized.
        v = closest.parameterV.get() / vScalar

        follicle.parameterU.set(u)
        follicle.parameterV.set(v)

        follicle.outTranslate >> trans.translate
        follicle.outRotate >> trans.rotate
        trans.translate.lock()
        trans.rotate.lock()
        hairJoint.setParent(trans)

    constraints = util.constrainAtoB(chain, controlChain)

    temp = core.capi.asMObject(surfaceShape)
    nurbsObj = OpenMaya.MFnNurbsSurface(temp.object())

    controls = []
    controlJoints = []
    for i in range(numControls):
        percent = i / float(numControls - 1) * vScalar
        p = pointOnSurface(surfaceShape, u=.5, v=percent, p=True)

        ctrl = controllerShape.build(
            name + '%i' % (i + 1),
            controlSpec['main'],
            type=controllerShape.ControlType.TRANSLATE)

        ctrl.t.set(p)
        j = joint(ctrl)
        hide(j)
        controlJoints.append(j)

        ctrl.setParent(container)

        # Aim the control at the next joint with it's up following the surface
        if i < numControls - 1:
            target = chain[i + 1]
            normal = nurbsObj.normal(0.5, percent)
            lib.anim.orientJoint(ctrl,
                                 target,
                                 upVector=dt.Vector(normal.x, normal.y,
                                                    normal.z))
            core.dagObj.zero(ctrl)

        controls.append(ctrl)

    # Orient the final control to the final joint
    core.dagObj.matchTo(controls[-1], chain[-1])
    core.dagObj.zero(controls[-1])

    skinCluster(surfaceShape, controlJoints, tsb=True)

    mainCtrl = nodeApi.RigController.convert(controls[0])
    mainCtrl.container = container
    for i, ctrl in enumerate(controls[1:], 1):
        mainCtrl.subControl[str(i)] = ctrl

    return mainCtrl, constraints
예제 #5
0
    def compute(self, plug, dataBlock):
        if plug not in [self.output]:
            self.displayWarning(error='Unknown plug: {}'.format(plug))
            return

        enabled = dataBlock.inputValue(self.enabled).asBool()
        offsetExtendsPosition = dataBlock.inputValue(
            self.offsetExtendsPosition).asBool()
        offset = dataBlock.inputValue(self.offset).asFloat()
        output_arrayHandle = dataBlock.outputArrayValue(self.output)
        output_builder = output_arrayHandle.builder()

        # get ray data
        indices = []
        enablesExtra = []
        inverseMatrices = []

        raySources = []
        rayDirections = []
        hitPositions = []
        hitDistances = []
        offsetVectors = []

        inputArrayHandle = dataBlock.inputArrayValue(self.input)
        for x in range(len(inputArrayHandle)):
            # get maya array input attributes
            inputArrayHandle.jumpToPhysicalElement(x)
            inputTargetHandle = inputArrayHandle.inputValue()
            index = inputArrayHandle.elementLogicalIndex()
            indices.append(index)
            position1 = om.MFloatPoint(
                inputTargetHandle.child(self.position1).asFloat3())
            position2 = om.MFloatPoint(
                inputTargetHandle.child(self.position2).asFloat3())
            eachOffset = offset + inputTargetHandle.child(
                self.offsetExtra).asFloat()
            inverseMatrices.append(
                inputTargetHandle.child(
                    self.parentInverseMatrix).asFloatMatrix())
            enablesExtra.append(
                inputTargetHandle.child(self.enabledExtra).asBool())
            if not enabled or not enablesExtra[-1]:
                eachOffset = 0

            # calculate ray
            rayDirection = position2 - position1
            offsetVectors.append(rayDirection.normal() * eachOffset)
            if offsetExtendsPosition and eachOffset < 0:
                position1 += offsetVectors[-1]
                rayDirection -= offsetVectors[-1]
            hitDistances.append(rayDirection.length())
            raySources.append(position1)
            rayDirections.append(rayDirection)
            hitPositions.append(position2)

        if enabled:

            # geometry loop
            inputGeometryArrayHandle = dataBlock.inputArrayValue(
                self.inputGeometry)
            for physicalGeoIndex in range(len(inputGeometryArrayHandle)):
                inputGeometryArrayHandle.jumpToPhysicalElement(
                    physicalGeoIndex)
                inputGeometryHandle = inputGeometryArrayHandle.inputValue()
                targetData = inputGeometryHandle.data()
                if targetData.isNull():
                    continue
                targetType = inputGeometryHandle.type()
                if targetType == om.MFnMeshData.kMesh:
                    meshFn = om.MFnMesh(targetData)

                    def getClosestHit(source, direction):
                        meshHit = meshFn.closestIntersection(
                            source, direction, om.MSpace.kWorld, 1, False)[0]
                        if meshHit == om.MFloatPoint():
                            return None
                        return meshHit
                elif targetType == om.MFnNurbsSurfaceData.kNurbsSurface:
                    nurbsFn = om.MFnNurbsSurface(targetData)

                    def getClosestHit(source, direction):
                        nurbsHit = nurbsFn.intersect(om.MPoint(source),
                                                     om.MVector(direction),
                                                     om.MSpace.kWorld)
                        if nurbsHit is None:
                            return None
                        return om.MFloatPoint(nurbsHit[0])
                else:
                    raise ValueError(
                        'unknown targetType: {}'.format(targetType))

                # ray loop
                for x, (index, enabledExtra, raySource,
                        rayDirection) in enumerate(
                            zip(indices, enablesExtra, raySources,
                                rayDirections)):
                    if not enabledExtra:
                        continue
                    hit = getClosestHit(raySource, rayDirection)
                    if hit is None:
                        continue
                    hitDistance = (hit - raySource).length()
                    if hitDistance < hitDistances[x]:
                        hitPositions[x] = hit
                        hitDistances[x] = hitDistance

        # set output
        for index, hitPosition, offsetVector, inverseMatrix in zip(
                indices, hitPositions, offsetVectors, inverseMatrices):
            output_handle = output_builder.addElement(index)
            outputPosition = (hitPosition - offsetVector) * inverseMatrix
            output_handle.set3Float(outputPosition[0], outputPosition[1],
                                    outputPosition[2])

        output_arrayHandle.set(output_builder)
        output_arrayHandle.setAllClean()
        dataBlock.setClean(plug)
예제 #6
0
def attach_to_surface(surface, dag):
    """Takes a dag node and attaches it to the nearest point on a surface,
       replacement for a follicle
    Args:
         surface (str): name of the transform of the nurbs surface that the dag
                        node will be attached to
         dag (str): name of the dag node which will be attached
    Returns:
        str: Name of transform that follows the surface
    """

    # nodes to attach dag to surface
    POSI = cmds.createNode('pointOnSurfaceInfo', name=dag + '_POSI')
    matrix_node = cmds.createNode('fourByFourMatrix', name=dag + '_4X4')
    foll = cmds.createNode('transform', name=dag + '_custom_foll')
    foll_MSC = cmds.createNode('millSimpleConstraint', name=foll + '_MSC')
    MM = cmds.createNode('multMatrix', name=dag + '_MM')

    # find closest point on surface and it's UV values
    sel = om.MSelectionList()
    sel.add(surface)

    plane = om.MFnNurbsSurface()
    plane.setObject(sel.getDagPath(0))

    point = om.MPoint(om.MVector(cmds.xform(dag, t=True, ws=True, q=True)))

    pos, parU, parV = plane.closestPoint(point)

    cmds.xform(dag, t=(pos[0], pos[1], pos[2]), ws=True)

    # attach dag to surface
    cmds.connectAttr(surface + '.local', POSI + '.inputSurface')
    cmds.setAttr(POSI + '.parameterU', parU)
    cmds.setAttr(POSI + '.parameterV', parV)

    # create matrix from POSI node
    cmds.connectAttr(POSI + '.normalizedTangentVX', matrix_node + '.in00')
    cmds.connectAttr(POSI + '.normalizedTangentVY', matrix_node + '.in01')
    cmds.connectAttr(POSI + '.normalizedTangentVZ', matrix_node + '.in02')
    cmds.connectAttr(POSI + '.normalizedNormalX', matrix_node + '.in10')
    cmds.connectAttr(POSI + '.normalizedNormalY', matrix_node + '.in11')
    cmds.connectAttr(POSI + '.normalizedNormalZ', matrix_node + '.in12')
    cmds.connectAttr(POSI + '.normalizedTangentUX', matrix_node + '.in20')
    cmds.connectAttr(POSI + '.normalizedTangentUY', matrix_node + '.in21')
    cmds.connectAttr(POSI + '.normalizedTangentUZ', matrix_node + '.in22')
    cmds.connectAttr(POSI + '.positionX', matrix_node + '.in30')
    cmds.connectAttr(POSI + '.positionY', matrix_node + '.in31')
    cmds.connectAttr(POSI + '.positionZ', matrix_node + '.in32')

    cmds.connectAttr(matrix_node + '.output', MM + '.matrixIn[0]')
    cmds.connectAttr(surface + '.worldMatrix[0]', MM + '.matrixIn[1]')

    cmds.connectAttr(MM + '.matrixSum', foll_MSC + '.inMatrix')
    cmds.connectAttr(foll + '.parentInverseMatrix[0]',
                     foll_MSC + '.parentInverseMatrix')

    cmds.connectAttr(foll_MSC + '.outTranslate', foll + '.translate')
    cmds.connectAttr(foll_MSC + '.outRotate', foll + '.rotate')

    constraint.simple_constraint(foll, dag)

    return foll
예제 #7
0
    def compute(self, plug, dataBlock):
        if plug not in [self.output]:
            self.displayWarning(error='Unknown plug: {}'.format(plug))
            return

        enabled = dataBlock.inputValue(self.enabled).asBool()
        offsetExtendsPositions = dataBlock.inputValue(
            self.offsetExtendsPositions).asBool()
        offset = dataBlock.inputValue(self.offset).asFloat()

        output_arrayHandle = dataBlock.outputArrayValue(self.output)
        output_builder = output_arrayHandle.builder()

        indices = []
        position1_list = []
        position2_list = []
        inverseMatrices = {}
        finalOffsets = []
        enablesExtra = []

        raySources = []
        rayDirections = []

        # get rays
        inputArrayHandle = dataBlock.inputArrayValue(self.input)
        for i in range(len(inputArrayHandle)):
            inputArrayHandle.jumpToPhysicalElement(i)
            inputTargetHandle = inputArrayHandle.inputValue()
            index = inputArrayHandle.elementLogicalIndex()
            indices.append(index)
            position1 = om.MFloatPoint(
                inputTargetHandle.child(self.position1).asFloat3())
            position1_list.append(position1)
            position2 = om.MFloatPoint(
                inputTargetHandle.child(self.position2).asFloat3())
            position2_list.append(position2)
            finalOffset = offset + inputTargetHandle.child(
                self.offsetExtra).asFloat()
            raySource = position1
            rayDirection = position2 - position1
            if offsetExtendsPositions and finalOffset:
                offsetVector = rayDirection.normal() * finalOffset
                if finalOffset > 0:
                    rayDirection += offsetVector
                elif finalOffset < 0:
                    raySource += offsetVector
            raySources.append(raySource)
            rayDirections.append(rayDirection)
            finalOffsets.append(finalOffset)
            inverseMatrices[index] = inputTargetHandle.child(
                self.parentInverseMatrix).asFloatMatrix()
            enablesExtra.append(
                inputTargetHandle.child(self.enabledExtra).asBool())

        # find closest intersections
        closestHits = {i: None for i in indices}
        offsetVectors = {i: None for i in indices}
        if enabled:
            inputGeometryArrayHandle = dataBlock.inputArrayValue(
                self.inputGeometry)
            for i in range(len(inputGeometryArrayHandle)):
                inputGeometryArrayHandle.jumpToPhysicalElement(i)
                inputGeometryHandle = inputGeometryArrayHandle.inputValue()
                targetData = inputGeometryHandle.data()
                if targetData.isNull():
                    continue

                targetType = inputGeometryHandle.type()
                if targetType == om.MFnMeshData.kMesh:
                    meshFn = om.MFnMesh(targetData)

                    def getClosestHit(source, direction):
                        meshHit = meshFn.closestIntersection(
                            source, direction, om.MSpace.kWorld, 1, False)[0]
                        if meshHit == om.MFloatPoint():
                            return None
                        return meshHit
                elif targetType == om.MFnNurbsSurfaceData.kNurbsSurface:
                    nurbsFn = om.MFnNurbsSurface(targetData)

                    def getClosestHit(source, direction):
                        nurbsHit = nurbsFn.intersect(om.MPoint(source),
                                                     om.MVector(direction),
                                                     om.MSpace.kWorld)
                        if nurbsHit is None:
                            return None
                        return om.MFloatPoint(nurbsHit[0])
                else:
                    raise ValueError(
                        'unknown targetType: {}'.format(targetType))

                for index, raySource, rayDirection, finalOffset, enabledExtra in zip(
                        indices, raySources, rayDirections, finalOffsets,
                        enablesExtra):
                    if not enabledExtra:
                        continue
                    hit = getClosestHit(raySource, rayDirection)
                    if hit is None:
                        continue
                    if closestHits[index] is None or \
                            (hit - raySource).length() < (closestHits[index] - raySource).length():
                        closestHits[index] = hit
                        if finalOffset:
                            closestHitVector = raySource - hit
                            if finalOffset > closestHitVector.length():
                                offsetVectors[index] = closestHitVector
                            else:
                                offsetVectors[index] = closestHitVector.normal(
                                ) * finalOffset

        # set output
        for index, hit in closestHits.iteritems():
            output_handle = output_builder.addElement(index)
            if hit is None:
                hit = position2_list[indices.index(index)]
            elif offsetVectors[index]:
                hit += offsetVectors[index]
            hit *= inverseMatrices[index]
            output_handle.set3Float(hit[0], hit[1], hit[2])

        output_arrayHandle.set(output_builder)
        output_arrayHandle.setAllClean()
        dataBlock.setClean(plug)
예제 #8
0
    def Apply(self, matrix):
        maya_cmds.undoInfo(stateWithoutFlush=False)
        try:
            shapes = maya_cmds.ls(maya_cmds.listRelatives(self.transforms,
                                                          path=True,
                                                          allDescendents=True),
                                  shapes=True)

            pivR = []
            pivS = []
            for i in xrange(len(self.transforms)):
                pivR.append(
                    maya_cmds.xform(self.transforms[i],
                                    q=True,
                                    worldSpace=True,
                                    rotatePivot=True))
                pivS.append(
                    maya_cmds.xform(self.transforms[i],
                                    q=True,
                                    worldSpace=True,
                                    scalePivot=True))
                maya_cmds.xform(self.transforms[i],
                                worldSpace=True,
                                zeroTransformPivots=True)

            mPoints = []
            for i in xrange(len(shapes)):
                mDagPath = OpenMaya.MGlobal.getSelectionListByName(
                    shapes[i]).getDagPath(0)
                objectType = maya_cmds.objectType(shapes[i])
                if objectType == 'mesh':
                    mPoints.append(
                        OpenMaya.MFnMesh(mDagPath).getPoints(
                            OpenMaya.MSpace.kWorld))
                elif objectType == 'nurbsCurve':
                    mPoints.append(
                        OpenMaya.MFnNurbsCurve(mDagPath).cvPositions(
                            OpenMaya.MSpace.kWorld))
                elif objectType == 'nurbsSurface':
                    mPoints.append(
                        OpenMaya.MFnNurbsSurface(mDagPath).cvPositions(
                            OpenMaya.MSpace.kWorld))
                else:
                    raise TypeError('Not supported object type: ' + objectType)

            for i in xrange(len(self.transforms)):
                if self.matrixIs.movX:
                    maya_cmds.setAttr(self.transforms[i] + '.translateX',
                                      matrix[i].movX)
                if self.matrixIs.movY:
                    maya_cmds.setAttr(self.transforms[i] + '.translateY',
                                      matrix[i].movY)
                if self.matrixIs.movZ:
                    maya_cmds.setAttr(self.transforms[i] + '.translateZ',
                                      matrix[i].movZ)
                if self.matrixIs.rotX:
                    maya_cmds.setAttr(self.transforms[i] + '.rotateX',
                                      matrix[i].rotX)
                if self.matrixIs.rotY:
                    maya_cmds.setAttr(self.transforms[i] + '.rotateY',
                                      matrix[i].rotY)
                if self.matrixIs.rotZ:
                    maya_cmds.setAttr(self.transforms[i] + '.rotateZ',
                                      matrix[i].rotZ)
                if self.matrixIs.scaX:
                    maya_cmds.setAttr(self.transforms[i] + '.scaleX',
                                      matrix[i].scaX)
                if self.matrixIs.scaY:
                    maya_cmds.setAttr(self.transforms[i] + '.scaleY',
                                      matrix[i].scaY)
                if self.matrixIs.scaZ:
                    maya_cmds.setAttr(self.transforms[i] + '.scaleZ',
                                      matrix[i].scaZ)
                maya_cmds.xform(self.transforms[i],
                                worldSpace=True,
                                rotatePivot=pivR[i],
                                scalePivot=pivS[i])

            for i in xrange(len(shapes)):
                mDagPath = OpenMaya.MGlobal.getSelectionListByName(
                    shapes[i]).getDagPath(0)
                objectType = maya_cmds.objectType(shapes[i])
                if objectType == 'mesh':
                    mFnMesh = OpenMaya.MFnMesh(mDagPath)
                    mFnMesh.setPoints(mPoints[i], OpenMaya.MSpace.kWorld)
                    mFnMesh.updateSurface()
                elif objectType == 'nurbsCurve':
                    mFnNurbsCurve = OpenMaya.MFnNurbsCurve(mDagPath)
                    mFnNurbsCurve.setCVPositions(mPoints[i],
                                                 OpenMaya.MSpace.kWorld)
                    mFnNurbsCurve.updateCurve()
                elif objectType == 'nurbsSurface':
                    mFnNurbsSurface = OpenMaya.MFnNurbsSurface(mDagPath)
                    mFnNurbsSurface.setCVPositions(mPoints[i],
                                                   OpenMaya.MSpace.kWorld)
                    mFnNurbsSurface.updateSurface()
        except Exception as e:
            print >> stderr, str(e)
        maya_cmds.undoInfo(stateWithoutFlush=True)