Пример #1
0
    def doSimpleSolver(self):
        """
		Solve single joint in the x-y plane
			- first it calculates the angle between the handle and the end-effector.
			- then it determines which way to rotate the joint.
		"""
        handle_group = self.handleGroup()
        handle = handle_group.handle(0)
        handlePath = OpenMaya.MDagPath.getAPathTo(handle)
        fnHandle = OpenMayaAnim.MFnIkHandle(handlePath)

        # Get the position of the end_effector
        end_effector = OpenMaya.MDagPath()
        fnHandle.getEffector(end_effector)
        tran = OpenMaya.MFnTransform(end_effector)
        effector_position = tran.rotatePivot(OpenMaya.MSpace.kWorld)

        # Get the position of the handle
        handle_position = fnHandle.rotatePivot(OpenMaya.MSpace.kWorld)

        # Get the start joint position
        start_joint = OpenMaya.MDagPath()
        fnHandle.getStartJoint(start_joint)
        start_transform = OpenMaya.MFnTransform(start_joint)
        start_position = start_transform.rotatePivot(OpenMaya.MSpace.kWorld)

        # Calculate the rotation angle
        v1 = start_position - effector_position
        v2 = start_position - handle_position
        angle = v1.angle(v2)

        # -------- Figure out which way to rotate --------
        #
        #  define two vectors U and V as follows
        #  U   =   EndEffector(E) - StartJoint(S)
        #  N   =   Normal to U passing through EndEffector
        #
        #  Clip handle_position to half-plane U to determine the region it
        #  lies in. Use the region to determine  the rotation direction.
        #
        #             U
        #             ^              Region      Rotation
        #             |  B
        #            (E)---N            A          C-C-W
        #         A   |                 B           C-W
        #             |  B
        #             |
        #            (S)
        #

        rot = 0.0  # Rotation about Z-axis

        # U and N define a half-plane to clip the handle against
        U = effector_position - start_position
        U.normalize()

        # Get a normal to U
        zAxis = OpenMaya.MVector(0.0, 0.0, 1.0)
        N = U ^ zAxis  # Cross product
        N.normalize()

        # P is the handle position vector
        P = handle_position - effector_position

        # Determine the rotation direction
        PdotN = P[0] * N[0] + P[1] * N[1]
        if PdotN < 0:
            rot = angle  # counter-clockwise
        else:
            rot = -1.0 * angle  # clockwise

        # get and set the Joint Angles
        jointAngles = OpenMaya.MDoubleArray()
        try:
            self._getJointAngles(jointAngles)
        except:
            # getting angles failed, do nothing
            pass
        else:
            jointAngles.set(jointAngles[0] + rot, 0)
            self._setJointAngles(jointAngles)
Пример #2
0
 def set_blend_weights(self, dag_path, components):
     blend_weights = om.MDoubleArray(len(self.data['blendWeights']))
     for i, w in enumerate(self.data['blendWeights']):
         blend_weights.set(w, i)
     self.fn.setBlendWeights(dag_path, components, blend_weights)
Пример #3
0
def addParticlePosToScatter(operation, toleranceForRemove):
    sel = mom.MSelectionList()
    mom.MGlobal.getActiveSelectionList(sel)
    scatterDag = mom.MDagPath()

    ##clear scatter data
    if (operation == 3) and (sel.length() == 1):
        sel.getDagPath(0, scatterDag)
        scatterDag.extendToShape()
        dgFn = mom.MFnDependencyNode(scatterDag.node())
        sctModePlug = dgFn.findPlug('scatterMode')
        sctMd = sctModePlug.asShort()
        mom.MGlobal.displayInfo('JCFeather : Scatter operate on node ' +
                                dgFn.name())
        mom.MGlobal.displayInfo('JCFeather : Clear scatter user point array.')
        if sctMd == 1:
            clearJCScatterUserData(scatterDag)
        elif sctMd == 2:
            clearJCScatterInPosition(scatterDag)
        return

    if sel.length() != 2:
        mom.MGlobal.displayError(
            'JCFeather : Select a particle and a jcScatter node.')

    particleDag = mom.MDagPath()
    particleComponent = mom.MObject()
    sel.getDagPath(0, particleDag, particleComponent)

    sel.getDagPath(1, scatterDag)
    scatterDag.extendToShape()
    dgFn = mom.MFnDependencyNode(scatterDag.node())
    growMeshPlug = dgFn.findPlug('inGrowMesh')
    sctModePlug = dgFn.findPlug('scatterMode')
    sctMd = sctModePlug.asShort()

    plugArray = mom.MPlugArray()
    growMeshPlug.connectedTo(plugArray, 1, 0)
    if plugArray.length() == 0:
        return

    mom.MGlobal.displayInfo('JCFeather : Scatter operate on node ' +
                            dgFn.name())

    if sctMd == 1:
        ##############################################     if the jcScatter is in UV scatter mode

        mom.MGlobal.displayInfo('JCFeather : Scatter UV mode.')

        uAryPlug = dgFn.findPlug('userUArray')
        vAryPlug = dgFn.findPlug('userVArray')
        uArray = mom.MDoubleArray()
        vArray = mom.MDoubleArray()
        if (getParticleClosestUVOnMesh(particleDag, particleComponent,
                                       plugArray[0].node(), uArray,
                                       vArray) == 0):
            return
        mom.MGlobal.displayInfo('JCFeather : Select particle data size ' +
                                str(uArray.length()))
        if operation == 1:
            ######################################          replace
            uDDFn = mom.MFnDoubleArrayData()
            vDDFn = mom.MFnDoubleArrayData()
            uAryPlug.setMObject(uDDFn.create(uArray))
            vAryPlug.setMObject(vDDFn.create(vArray))
            mom.MGlobal.displayInfo(
                'JCFeather : Replace scatter userUVArray data.')
        elif operation == 0:
            ######################################          add
            defaultVecArray = mom.MDoubleArray()
            try:
                uDDFn = mom.MFnDoubleArrayData(uAryPlug.asMObject())
            except:
                uDDFn = mom.MFnDoubleArrayData()
                uAryPlug.setMObject(uDDFn.create(defaultVecArray))
            try:
                vDDFn = mom.MFnDoubleArrayData(vAryPlug.asMObject())
            except:
                vDDFn = mom.MFnDoubleArrayData()
                vAryPlug.setMObject(vDDFn.create(defaultVecArray))

            oldUArray = uDDFn.array()
            oldVArray = vDDFn.array()
            oldLen = oldUArray.length()
            addNewUvToUV(oldUArray, oldVArray, uArray, vArray,
                         toleranceForRemove)

            uAryPlug.setMObject(uDDFn.object())
            vAryPlug.setMObject(vDDFn.object())
            mom.MGlobal.displayInfo(
                'JCFeather : Add scatter userUVArray data. ' + str(oldLen) +
                ' --> ' + str(oldUArray.length()))
        elif operation == 2:
            ######################################      remove
            try:
                uDDFn = mom.MFnDoubleArrayData(uAryPlug.asMObject())
            except:
                mom.MGlobal.displayError(
                    "JCFeather : No userUArray data to remove.")
            try:
                vDDFn = mom.MFnDoubleArrayData(vAryPlug.asMObject())
            except:
                mom.MGlobal.displayError(
                    "JCFeather : No userVArray data to remove.")

            oldUArray = uDDFn.array()
            oldVArray = vDDFn.array()

            newULen = uArray.length()
            oldULen = oldUArray.length()

            resultU = mom.MDoubleArray()
            resultV = mom.MDoubleArray()

            for j in range(0, oldUArray.length()):
                for i in range(0, newULen):
                    if isDistanceSmaller(oldUArray[j], oldVArray[j], uArray[i],
                                         vArray[i], toleranceForRemove) == 1:
                        oldUArray.remove(j)
                        oldVArray.remove(j)
            uAryPlug.setMObject(uDDFn.object())
            vAryPlug.setMObject(vDDFn.object())
            mom.MGlobal.displayInfo(
                'JCFeather : Remove scatter userUVArray data. ' +
                str(oldULen) + ' --> ' + str(oldUArray.length()))
    elif sctMd == 2:
        ##### if the jcScatter is in InPosition scatter mode

        mom.MGlobal.displayInfo('JCFeather : Scatter inPosition mode.')
        inPositionPlug = dgFn.findPlug('inPosition')
        clstPtAry = getPartticlePos(particleDag, particleComponent)

        print('JCFeather : Select particle data size ' +
              str(clstPtAry.length()))
        if operation == 1:
            ###########################                            replace
            uDDFn = mom.MFnVectorArrayData()
            inPositionPlug.setMObject(uDDFn.create(clstPtAry))
            mom.MGlobal.displayInfo(
                'JCFeather : Replace scatter inPosition data.')
        elif operation == 0:
            ############################                             add
            try:
                uDDFn = mom.MFnVectorArrayData(inPositionPlug.asMObject())
            except:

                uDDFn = mom.MFnVectorArrayData()
                defaultVecArray = mom.MVectorArray()
                inPositionPlug.setMObject(uDDFn.create(defaultVecArray))

            myOldVecAry = uDDFn.array()
            oldLen = myOldVecAry.length()
            addNewParticleToVector(clstPtAry, myOldVecAry, toleranceForRemove)
            inPositionPlug.setMObject(uDDFn.object())
            mom.MGlobal.displayInfo(
                'JCFeather : Add scatter inPosition data. ' + str(oldLen) +
                ' --> ' + str(myOldVecAry.length()))
        elif operation == 2:
            #############################                            remove
            try:
                uDDFn = mom.MFnVectorArrayData(inPositionPlug.asMObject())
            except:
                mom.MGlobal.displayError(
                    "JCFeather : No inPosition data to remove.")
            oldVArray = uDDFn.array()

            newULen = clstPtAry.length()
            oldULen = oldVArray.length()

            result = mom.MVectorArray()
            idAry = mom.MIntArray()
            for j in range(0, oldVArray.length()):
                for i in range(0, newULen):
                    dist = mom.MPoint(oldVArray[j].x, oldVArray[j].y,
                                      oldVArray[j].z).distanceTo(
                                          mom.MPoint(clstPtAry[i].x,
                                                     clstPtAry[i].y,
                                                     clstPtAry[i].z))
                    if dist < toleranceForRemove:
                        oldVArray.remove(j)
            inPositionPlug.setMObject(uDDFn.object())
            mom.MGlobal.displayInfo(
                'JCFeather : Remove scatter inPosition data. ' + str(oldULen) +
                ' --> ' + str(oldVArray.length()))
        def findSurfaceIntersections(self):
            '''
            Return the pierced points on a surface from a raySource and rayDir
            '''        
            try:
                self._str_funcName = 'findSurfaceIntersections'
                log.debug(">>> %s >> "%self._str_funcName + "="*75)
                if len(mc.ls(surface))>1:
                    raise StandardError,"findSurfaceIntersections>>> More than one surface named: %s"%surface

                self.centerPoint = mc.xform(surface, q=1, ws=1, t=1)

                #checking the type 
                self.objType = search.returnObjectType(surface)
                
                if self.objType == 'nurbsSurface':
                    raySource = om.MPoint(raySource[0], raySource[1], raySource[2])
                    self.raySourceVector = om.MVector(raySource[0], raySource[1], raySource[2])
                    self.centerPointVector = om.MVector(self.centerPoint[0],self.centerPoint[1],self.centerPoint[2])
                    rayDir = om.MPoint(self.centerPointVector - self.raySourceVector)
                    self.rayDirection = om.MVector(rayDir[0], rayDir[1], rayDir[2])
                    self.hitPoints = om.MPoint()
                    self.selectionList = om.MSelectionList()
                    self.selectionList.add(surface)
                    self.surfacePath = om.MDagPath()
                    self.selectionList.getDagPath(0, self.surfacePath)
                    self.surfaceFn = om.MFnNurbsSurface(self.surfacePath)
                    
                    #maxDist
                    self.maxDist = maxDistance

                    #other variables 
                    self.u = om.MDoubleArray()
                    self.v = om.MDoubleArray()
                    self.spc = om.MSpace.kWorld
                    self.toleranceSU = om.MScriptUtil()
                    self.tolerance = self.toleranceSU.asDoublePtr()
                    om.MScriptUtil.setDouble(self.tolerance, .1)

                    #Get the closest intersection.
                    self.gotHit = self.surfaceFn.intersect(raySource,self.rayDirection,self.u,self.v,self.hitPoints,self.toleranceSU.asDouble(),self.spc,False,None,False,None)
                    
                elif self.objType == 'mesh':
                    raySource = om.MFloatPoint(raySource[0], raySource[1], raySource[2])
                    self.raySourceVector = om.MFloatVector(raySource[0], raySource[1], raySource[2])
                    self.centerPointVector = om.MFloatVector(self.centerPoint[0],self.centerPoint[1],self.centerPoint[2]) 
                    rayDir = om.MFloatPoint(self.centerPointVector - self.raySourceVector)
                    self.rayDirection = om.MFloatVector(rayDir[0], rayDir[1], rayDir[2])
                    self.hitPoints = om.MFloatPointArray()             
                    self.selectionList = om.MSelectionList()
                    self.selectionList.add(surface)
                    self.meshPath = om.MDagPath()
                    self.selectionList.getDagPath(0, self.meshPath)
                    self.meshFn = om.MFnMesh(self.meshPath)

                    #maxDist
                    self.maxDist = maxDistance

                    #other variables
                    self.spc = om.MSpace.kWorld

                    #Get the closest intersection.
                    self.gotHit = self.meshFn.allIntersections(raySource,self.rayDirection,None,None,False,self.spc,self.maxDist,False,None,False,self.hitPoints,None,None,None,None,None)
                 
                else : raise StandardError,"wrong surface type!"
                    
                #Return the intersection as a Python list.
                if self.gotHit:
                    self.returnDict = {}
                    self.hitList = []
                    self.uvList = []
                    for i in range( self.hitPoints.length() ):
                        self.hitList.append( [self.hitPoints[i].x, self.hitPoints[i].y, self.hitPoints[i].z])
                        self.hitMPoint = om.MPoint(self.hitPoints[i])
                        self.pArray = [0.0,0.0]
                        self.x1 = om.MScriptUtil()
                        self.x1.createFromList(pArray, 2)
                        self.uvPoint = x1.asFloat2Ptr()
                        self.uvSet = None
                        self.uvReturn = self.surfaceFn.getParamAtPoint(self.hitMPoint,self.uvPoint,self.paramU,self.paramV, self.ignoreTrimBoundaries, om.MSpace.kObject, self.kMFnNurbsEpsilon)
                                    
                        self.uValue = om.MScriptUtil.getFloat2ArrayItem(self.uvPoint, 0, 0) or False
                        self.vValue = om.MScriptUtil.getFloat2ArrayItem(uvPoint, 0, 1) or False
                        self.uvList.append([self.uValue,self.vValue])
                                    
                        self.returnDict = {'hits':self.hitList,'source':[raySource.x,raySource.y,raySource.z],'uvs':self.uvList}
                        return self.returnDict
                else: return None
                        
            except StandardError,error:
                log.error(">>> surface | raysource | rayDir | error")
                return None
Пример #5
0
def collectBlendWeights(skinCls, dagPath, components, dataDic):
    weights = OpenMaya.MDoubleArray()
    skinCls.__apimfn__().getBlendWeights(dagPath, components, weights)
    dataDic['blendWeights'] = [weights[i] for i in range(weights.length())]
Пример #6
0
    def loadWeights(self,
                    skinCluster=None,
                    influenceList=None,
                    componentList=None,
                    normalize=True):
        '''
		Apply the stored skinCluster weights.
		@param skinCluster: The list of components to apply skinCluster weights to.
		@type skinCluster: str
		@param influenceList: The list of skinCluster influences to apply weights for.
		@type influenceList: list or None
		@param componentList: The list of components to apply skinCluster weights to.
		@type componentList: list or None
		@param normalize: Normalize influence weights.
		@type normalize: bool
		'''
        # ==========
        # - Checks -
        # ==========

        # Check SkinCluster
        if not skinCluster: skinCluster = self._data['name']
        self.verifySkinCluster(skinCluster)

        # Check Geometry
        skinGeo = self._data['affectedGeometry'][0]
        if not mc.objExists(skinGeo):
            raise Exception(
                'SkinCluster geometry "' + skinGeo +
                '" does not exist! Use remapGeometry() to load skinCluster data to a different geometry!'
            )

        # Check Influence List
        if not influenceList: influenceList = self._influenceData.keys() or []
        for influence in influenceList:
            if not influence in mc.skinCluster(skinCluster, q=True,
                                               inf=True) or []:
                raise Exception('Object "' + influence +
                                '" is not a valid influence of skinCluster "' +
                                skinCluster +
                                '"! Unable to load influence weights...')
            if not self._influenceData.has_key(influence):
                raise Exception('No influence data stored for "' + influence +
                                '"! Unable to load influence weights...')

        # Check Component List
        if not componentList:
            componentList = glTools.utils.component.getComponentStrList(
                skinGeo)
        componentSel = glTools.utils.selection.getSelectionElement(
            componentList, 0)

        # Get Component Index List
        #indexList =  OpenMaya.MIntArray()
        #componentFn = OpenMaya.MFnSingleIndexedComponent(componentSel[1])
        #componentFn.getElements(indexList)
        #componentIndexList = list(indexList)
        componentIndexList = glTools.utils.component.getSingleIndexComponentList(
            componentList)
        componentIndexList = componentIndexList[componentIndexList.keys()[0]]

        # =====================================
        # - Set SkinCluster Influence Weights -
        # =====================================

        # Get Influence Index
        infIndexArray = OpenMaya.MIntArray()
        for influence in influenceList:
            infIndex = glTools.utils.skinCluster.getInfluencePhysicalIndex(
                skinCluster, influence)
            infIndexArray.append(infIndex)

        # Build Weight Array
        wtArray = OpenMaya.MDoubleArray()
        oldWtArray = OpenMaya.MDoubleArray()
        for c in componentIndexList:
            for i in range(len(influenceList)):
                if self._influenceData.has_key(influenceList[i]):
                    wtArray.append(
                        self._influenceData[influenceList[i]]['wt'][c])
                else:
                    wtArray.append(0.0)

        # Get skinCluster function set
        skinFn = glTools.utils.skinCluster.getSkinClusterFn(skinCluster)

        # Set skinCluster weights
        skinFn.setWeights(componentSel[0], componentSel[1], infIndexArray,
                          wtArray, normalize, oldWtArray)

        # =================
        # - Return Result -
        # =================

        return list(wtArray)
Пример #7
0
def bake(instancerName, start, end, progress=None):
    """
    Process an instancer node over the specified frame range, reading the 
    positions and objects. With this data objects are duplicated and 
    positioned to mimic the instancer. With the particle data individual 
    objects can be matched over the different frames and animated. When
    a particle "dies", the visibility is turned off.

    :param str instancerName: Name if the instancer to bake
    :param int start: Start frame
    :param int end: End frame
    :param QProgressBar progress: Update ui ( Optional )
    :return: Group that contains all of the baked information
    :rtype: str
    :raises RuntimeError: When the instancer doesn't exist
    :raises RuntimeError: When there are no particles attached
    """
    # store all particle information in data variable
    data = {}

    # get instance
    if not cmds.objExists(instancerName):
        raise RuntimeError("Instancer doesn't exist!")

    # set visible
    cmds.setAttr("{0}.visibility".format(instancerName), 1)

    instancerObj = utils.asMObject(instancerName)
    instancerDag = utils.asMDagPath(instancerObj)
    instancer = OpenMayaFX.MFnInstancer(instancerDag)

    # get particles
    particleName = cmds.listConnections(
        "{0}.inputPoints".format(instancerName))
    if not particleName:
        raise RuntimeError("No particles connected!")

    particleName = particleName[0]
    particleObj = utils.asMObject(particleName)
    particleDag = utils.asMDagPath(particleObj)
    particle = OpenMayaFX.MFnParticleSystem(particleDag)

    # variables
    ages = OpenMaya.MDoubleArray()
    paths = OpenMaya.MDagPathArray()
    matrices = OpenMaya.MMatrixArray()
    particleIndices = OpenMaya.MIntArray()
    pathIndices = OpenMaya.MIntArray()

    # create container group
    container = cmds.group(world=True,
                           empty=True,
                           n="{0}_bake_1".format(instancerName))

    # loop time
    for i in range(start, end + 1):
        # set time
        cmds.currentTime(i)

        # query instancer information
        instancer.allInstances(paths, matrices, particleIndices, pathIndices)

        # query particle information
        particle.age(ages)

        # loop particle instances
        num = matrices.length()
        for j in range(num):
            # get particles index
            p = particleIndices[j]

            # get parent
            parent = paths[pathIndices[j]].fullPathName()

            # get age
            age = ages[j]

            if data.get(p):
                # get path and age
                path = data[p].get("path")

                oldAge = data[p].get("age")
                oldParent = data[p].get("parent")

                # check if age is less than previous
                if age < oldAge:
                    # hide mesh and delete particle id data
                    utils.keyVisibility(path, i, 0)
                    del (data[p])

                # check if parent is the same as previous
                elif parent != oldParent:
                    # hide mesh and delete particle id data
                    utils.keyVisibility(path, i, 0)
                    del (data[p])

            # duplicate path if index not in data
            if not data.get(p):
                # get parent name
                parentShort = parent.split("|")[-1].split(":")[-1]

                # duplicate mesh
                name = "{0}_{1}_1".format(instancerName, parentShort)
                path = cmds.duplicate(parent, n=name)[0]
                path = cmds.parent(path, container)[0]

                # handle visibility
                utils.keyVisibility(path, i, 1)

                # get dag
                dag = utils.asMDagPath(utils.asMObject(path))

                # get matrix
                transform = utils.asMFnTransform(dag)
                matrix = transform.transformation().asMatrix()

                # store variables
                data[p] = {}
                data[p]["path"] = path
                data[p]["dag"] = dag
                data[p]["matrix"] = matrix
                data[p]["parent"] = parent

            # get variables
            path = data[p].get("path")
            dag = data[p].get("dag")
            matrix = data[p].get("matrix")

            # store age
            data[p]["age"] = age

            # set matrix
            m = matrix * matrices[j]
            m = OpenMaya.MTransformationMatrix(m)

            transform = utils.asMFnTransform(dag)
            transform.set(m)

            # set keyframes
            utils.keyTransform(path, i)

        # update progress
        if progress:
            progress.setValue(i + 1 - start)

    return container
Пример #8
0
    def vtxSave_Oapi(self):
        selList = Om.MSelectionList()
        Om.MGlobal.getActiveSelectionList(selList)
        #_prselList = []
        # selList.getSelectionStrings(_prselList)   #获取 MSelectionList 内容
        # print _prselList
        if selList.isEmpty():
            Om.MGlobal.displayError('Select Nothing')
            return
        MDagPath = Om.MDagPath()  # 存储所选物体的路径
        MObject = Om.MObject()  # 存储所选物体的组件的列表
        selList.getDagPath(0, MDagPath)
        selList.getDependNode(0, MObject)
        # MDagPath.fullPathName()   #获取 MDagPath 内容
        slMIt = Om.MItSelectionList(selList)
        MItDagPath = Om.MDagPath()
        MItcomponent = Om.MObject()
        slMIt.getDagPath(MItDagPath, MItcomponent)

        _selType = MDagPath.apiType()
        MDagPath.extendToShape()  # 获取当前物体的shape节点
        _selShapeType = MDagPath.apiType()
        if not _selType in set([110, 296, 267, 294, 279, ]):
            return
        elif _selShapeType == 296:
            suf = 'vtx'
        elif _selShapeType == 267 or _selShapeType == 294:
            suf = 'cv'
        elif _selShapeType == 279:
            suf = 'pt'

        skCluster = mel.eval('findRelatedSkinCluster("%s")' % MDagPath.partialPathName())
        if not skCluster:
            return
        #connectNode = cmds.listHistory(MDagPath.partialPathName(), il=1, pdo=1)
        # if not connectNode:
        #    Om.MGlobal.displayError('Select No Skin')
        #    return
        # for skCluster in connectNode:
        #    if cmds.nodeType(skCluster) == 'skinCluster':
        #        break
        #    if skCluster == connectNode[-1]:
        #        return
        Om.MGlobal.getSelectionListByName(skCluster, selList)
        skinObj = Om.MObject()
        selList.getDependNode(1, skinObj)
        skinNode = OmAni.MFnSkinCluster(skinObj)
        infs = Om.MDagPathArray()
        numInfs = skinNode.influenceObjects(infs)
        infNameList = []  # 骨骼列表
        for i in range(numInfs):
            infName = infs[i].partialPathName()
            infNameList.append(infName)
        # fn = Om.MFnDependencyNode(MDagPath.node())   #获取MDagPath的内容?
        # print fn.name()   #获取 MFnDependencyNode 内容

        filePath = cmds.fileDialog2(ff='WeightFile (*.vtxWeight *.sdd)', ds=2)  # vtxWeight (*.vtxWeight);;sdd (*.sdd)
        if not filePath:
            return
        fileLine = []
        Lineapp = fileLine.append
        if not MItcomponent.isNull():  # component组件不为空(点), 线和面会强制转为点
            vertIter = Om.MItGeometry(MItDagPath, MItcomponent)
        else:
            vertIter = Om.MItGeometry(MObject)
        while not vertIter.isDone():
            infCount = Om.MScriptUtil()
            infCountPtr = infCount.asUintPtr()
            Om.MScriptUtil.setUint(infCountPtr, 0)
            weights = Om.MDoubleArray()
            skinNode.getWeights(MDagPath, vertIter.currentItem(), weights, infCountPtr)

            tvList = self.zeroWeightData_Save(weights, infNameList)
            wtStr = '%s[%s]--%s\r\n' % (suf, vertIter.index(), tvList)
            Lineapp(wtStr)
            vertIter.next()
        with open(filePath[0], 'w') as vwfile:
            for i in fileLine:
                vwfile.write(i)
        DisplayYes().showMessage('Process Finish!')
Пример #9
0
    def vtxLoad_Oapi(self):
        selList = Om.MSelectionList()
        Om.MGlobal.getActiveSelectionList(selList)
        if selList.isEmpty():
            Om.MGlobal.displayError('Select Nothing')
            return
        elif selList.length() != 1:
            Om.MGlobal.displayError("Nothing selected")
        MDagPath = Om.MDagPath()  # 存储所选物体的路径
        MObject = Om.MObject()  # 存储所选物体的组件的列表
        selList.getDagPath(0, MDagPath)
        selList.getDependNode(0, MObject)
        # MDagPath.fullPathName()   #获取 MDagPath 内容

        _selType = MDagPath.apiType()
        if _selType != 110:
            Om.MGlobal.displayError('Please Select Object')
            return

        skCluster = mel.eval('findRelatedSkinCluster("%s")' % MDagPath.partialPathName())
        if not skCluster:
            return
        Om.MGlobal.getSelectionListByName(skCluster, selList)
        skinObj = Om.MObject()
        selList.getDependNode(1, skinObj)
        skinNode = OmAni.MFnSkinCluster(skinObj)
        infs = Om.MDagPathArray()
        numInfs = skinNode.influenceObjects(infs)
        infNameList = []  # 骨骼列表
        for i in range(numInfs):
            infName = infs[i].partialPathName()
            infNameList.append(infName)
        # fn = Om.MFnDependencyNode(MDagPath.node())   #获取MDagPath的内容?
        # print fn.name()   #获取 MFnDependencyNode 内容

        filePath = cmds.fileDialog2(ff='WeightFile (*.vtxWeight *.sdd)', ds=2, fm=1)
        if not filePath:
            return
        allLine = self.readWeightData_Load(filePath[0])
        if allLine == 'toMel':
            Om.MGlobal.displayWarning('Some Error. Please ReSelect')
            self.vtxLoad_Mel()
            return

        jntLock = []
        for j in infNameList:
            jntLock.append(cmds.getAttr(j + '.liw'))
            cmds.setAttr(j + '.liw', 0)
        vertIter = Om.MItGeometry(MObject)
        _Num = 0
        while not vertIter.isDone():
            if vertIter.index() != int(allLine[_Num][0]):
                vertIter.next()
                continue
            jntindex = Om.MIntArray()
            weights = Om.MDoubleArray()
            jntindexapp = jntindex.append
            weightsapp = weights.append
            for i in range(len(allLine[_Num][1])):
                jntindexapp(infNameList.index(allLine[_Num][1][i]))
                weightsapp(allLine[_Num][2][i])
            skinNode.setWeights(MDagPath, vertIter.currentItem(), jntindex, weights, False)  # False规格化开关默认为True
            _Num += 1
            vertIter.next()
        for j, l in zip(infNameList, jntLock):
            cmds.setAttr(j + '.liw', l)
        DisplayYes().showMessage('Process Finish!')
Пример #10
0
    def redoIt(self):
        # get the vertex to operating on
        self.component = om.MFnSingleIndexedComponent().create(
            om.MFn.kMeshVertComponent)
        om.MFnSingleIndexedComponent(self.component).addElement(self.index)

        # get surrounding vertices
        surrWeights = om.MDoubleArray(
        )  # storing weights of surrounding vertices
        msInf = om.MScriptUtil()  # script util for int pointer
        infCountPtr = msInf.asUintPtr(
        )  # unsigned int pointer sotring number of influences on the vertex
        surrVtxArray = om.MIntArray()  # storing sorrounding vertex indices

        # create iterator
        mitVtx = om.MItMeshVertex(self.dagPath, self.component)
        mitVtx.getConnectedVertices(surrVtxArray)
        surrComponents = om.MFnSingleIndexedComponent().create(
            om.MFn.kMeshVertComponent)
        om.MFnSingleIndexedComponent(surrComponents).addElements(surrVtxArray)

        # read weight from single vertex, store to oldWeights
        self.fnSkin.getWeights(self.dagPath, self.component, self.oldWeights,
                               infCountPtr)

        # read weight fromthe surrounding vertices, store to surrWeights
        self.fnSkin.getWeights(self.dagPath, surrComponents, surrWeights,
                               infCountPtr)

        # number of influences affecting the operating vertex
        influenceCount = om.MScriptUtil.getUint(infCountPtr)

        # reset variable infIndices
        infIndices_util = om.MScriptUtil()
        infIndices_util.createFromList(range(0, influenceCount),
                                       influenceCount)
        infIndices_iPtr = infIndices_util.asIntPtr()
        self.infIndices = om.MIntArray(infIndices_iPtr, influenceCount)

        # calculate multiplier for each surrounding vertices base on distance
        # distances = []
        # dist_append = distances.append
        # mPt = om.MPoint
        # mSpaceKObj = om.MSpace.kObject
        # fnOrigMesh_getPoint = self.fnOrigMesh.getPoint

        # get operating vertex point position on the orig mesh
        # compPt = mPt()
        # cPt_distTo = compPt.distanceTo
        # fnOrigMesh_getPoint(self.index, compPt, mSpaceKObj)

        # loop over each surrounding vertices to get distance to the operating vertex
        # for sIndx in sorted(surrVtxArray):
        # sPoint = mPt()
        # fnOrigMesh_getPoint(sIndx, sPoint, mSpaceKObj)
        # dist = cPt_distTo(sPoint)
        # dist_append(dist)

        # average all the surrounding vertex weights, multiply with the brush value and blend it over the origWeight
        oldWeight = self.oldWeights

        values = []
        values_append = values.append

        # pre-calculate what we can before entering the loop
        surrVtxCount = surrVtxArray.length()
        pressure = self.pressure
        pressure_sqr = pressure * pressure
        pre_mult = (1.0 / surrVtxCount) * (1.0 - pressure)

        # normalize and invert the distances, make closer distance has more value than the further ones
        # mults = [(sum(distances)/d)*pressure_sqr for d in distances]

        # the main weight value calculation loop
        for i in xrange(0, influenceCount):
            v = oldWeight[i] * pre_mult
            for w in xrange(0, surrVtxCount):
                # v += surrWeights[i + (w*influenceCount)] * mults[w]
                v += surrWeights[i + (w * influenceCount)] * pressure_sqr
            values_append(v)

        # do maintain max influences if maintainMaxInfluences is checked on the skinCluster node
        if self.maintainMaxInfluences == True:
            # get indices of the top N values
            maxIndexs = sorted(range(influenceCount),
                               key=lambda v: values[v],
                               reverse=True)[:self.maxInfluences]
            maxVals = [0] * influenceCount
            for i in maxIndexs:
                maxVals[i] = values[i]
        else:  # else, just use the calculated list
            maxVals = values

        # normalize
        normList = [w / sum(maxVals) for w in maxVals]

        # cast python list to MDoubleArray
        # newWeights
        newWeight_util = om.MScriptUtil()
        newWeight_util.createFromList(normList, influenceCount)
        newWeight_dPtr = newWeight_util.asDoublePtr()
        newWeights = om.MDoubleArray(newWeight_dPtr, influenceCount)

        # set the final weights throught the skinCluster
        self.fnSkin.setWeights(self.dagPath, self.component, self.infIndices,
                               newWeights, False, self.oldWeights)
Пример #11
0
    def buildData(self, curve, worldSpace=False):
        '''
		Build NurbsCurveData class.
		@param curve: Curve to build data from
		@type curve: str
		'''
        # ==========
        # - Checks -
        # ==========

        # Check Curve
        if not glTools.utils.curve.isCurve(curve):
            raise Exception('Object "' + curve +
                            '" is not a vaild NURBS curve node!')

        # World Space
        space = OpenMaya.MSpace.kObject
        if worldSpace: space = OpenMaya.MSpace.kWorld

        # ==============
        # - Build Data -
        # ==============

        # Start timer
        timer = mc.timerX()

        # Get basic curve info
        self._data['name'] = curve

        # Get Curve Function Class
        curveFn = glTools.utils.curve.getCurveFn(curve)

        # Get Curve Degree and Form
        self._data['degree'] = curveFn.degreeU()
        self._data['form'] = int(curveFn.formInU())

        # Get Curve Knots
        knotArray = OpenMaya.MDoubleArray()
        curveFn.getKnotsInU(knotArray)
        self._data['knots'] = list(knotArray)

        # Get Control Vertices
        cvArray = OpenMaya.MPointArray()
        curveFn.getCVs(cvArray, space)
        self._data['cv'] = [(cvArray[i].x, cvArray[i].y, cvArray[i].z)
                            for i in range(cvArray.length())]

        # Get Edit Points
        editPt = OPenMaya.MPoint()
        for u in self._data['knots']:
            curveFn.getPointAtParam(u, editPt, space)
            self._data['editPt'].append((editPt.x, editPt.y, editPt.z))

        # =================
        # - Return Result -
        # =================

        # Print timer result
        buildTime = mc.timerX(st=timer)
        print('NurbsCurveData: Data build time for curve "' + curve + '": ' +
              str(buildTime))

        return self._data['name']
class instanceRotate(OpenMayaMPx.MPxCommand):
	#- Store the base shape for the instances here for undo
	shapeObj = OpenMaya.MDagPath()
	#- Store the original rotation values for undo here
	rotations = OpenMaya.MDoubleArray()

	def __init__(self):
		OpenMayaMPx.MPxCommand.__init__(self)
		#- Store the user selection of the rotation axis (one axis for all of the instances)
		self.axis = AXIS_X
		#- Store the number of instances for one shape
		self.numInstances = 0

	#- This method is used to specify whether or not the command is undoable. In 
	#- the base class, it always returns false. If you are writing a command that 
	#- might be eligible for undo, you should override this method.
	#- After Maya executes the command's doIt method, it will call isUndoable. If 
	#- isUndoable returns true, Maya will retain the instance of the class and pass 
	#- it to Maya's undo manager so that the undoIt and redoIt methods can be called
	#- when appropriate. If isUndoable returns false, the command instance will be 
	#- immediately destroyed.
	#def isUndoable(self):
	#	return True

	#def hasSyntax(self):
	#	return True

	#- This method should perform a command by setting up internal class data
	#- and then calling the redoIt method if undo is supported by the command.
	#- The actual action performed by the command should be done in the redoIt 
	#- method. This is a pure virtual method, and must be overridden in derived 
	#- classes.
	def doIt(self, args):
		#- Since all the command actions will be done in the redoIt() method, this
		#- method will only parse the arguments. redoIt() will not use arguments
		#- at all.
		argParser = OpenMaya.MArgParser (self.syntax(),args)

		numFlags = argParser.numberOfFlagsUsed()
		if(numFlags != 1):
			OpenMaya.MGlobal.displayError("Simple Plugs requires one flag argument and a DAG object must be selected")
			return None
		else:
			if(argParser.isFlagSet(ROTATEFLAG) | argParser.isFlagSet(ROTATELONGFLAG)):
				#- The user enters 1, 2, or 3 to indicate x, y, or z rotation axis
				flag =argParser.flagArgumentInt(ROTATEFLAG,0)

				if(flag == AXIS_X):
					self.axis = AXIS_X
				elif(flag == AXIS_Y):
					self.axis = AXIS_Y
				elif(flag == AXIS_Z):
					self.axis = AXIS_Z
				else:
					OpenMaya.MGlobal.displayError("Invalid axis rotation argument")
					return None

		return self.redoIt(args)

	#- This method should do the actual work of the command based on the internal 
	#- class data only. Internal class data should be set in the doIt method.
	def redoIt(self, args):
		OpenMayaMPx.MPxCommand.setResult( "instanceRotate command executed!\n" )

		#- This is really where is the intelligence of the command. Here we will
		#- preform all the actions we wanted to implement for this command.

		#- Get the active selection in the Maya viewport.
		selList = OpenMaya.MSelectionList()
		OpenMaya.MGlobal.getActiveSelectionList(selList)

		if(selList.isEmpty()):
			OpenMaya.MGlobal.displayError("A single DAG object must be selected")
			return None

		dagPath = OpenMaya.MDagPath()
		selList.getDagPath(0,dagPath)

		#- Chances are the user selected the object from the panel view or
		#- outliner window so the object in the list will actually be a 
		#- transform node... if so we call extendToShape to grab the actual
		#- shape node from the dagPath
		
		#- TODO: Test if this node is a transform node, and if so extend the
		#- TODO: dagPath to the real shape node.
		#...
		#...

		if(dagPath.isInstanced()):
			self.shapeObj = dagPath
			self.rotate(dagPath)
		else:
			OpenMaya.MGlobal.displayError("The selected item is not an instanced DAG object")
			return None

	#- This method should undo the work done by the redoIt method based on the 
	#- internal class data only.
	def undoIt(self, args):
		OpenMaya.MGlobal.displayInfo( "instanceRotate command undone!\n" )
		
		fnDag = MFnDagNode(self.shapeObj)

		for i in range ( 0, self.numInstances ):
			currentParent = fnDag.parent(i)
			fnParent = OpenMaya.MFnDependencyNode(currentParent)
			rotPlug = fnParent.findPlug("rotate")
			if (self.axis == AXIS_X):
				rotxPlug = rotPlug.child(0)
				rotxPlug.setDouble(self.rotations[i])
			elif (self.axis == AXIS_Z):
				rotzPlug = rotPlug.child(2)
				rotzPlug.setDouble(self.rotations[i])
			else: # AXIS_Y:
				rotyPlug = rotPlug.child(1)
				rotyPlug.setDouble(self.rotations[i])

		#- Empty the array in case the user chooses redoIt
		self.rotations.clear()

	#- Method used by redoIt to assign a 45 degree rotation along a random axis.
	def rotate( self, dp ):
		#- The passed-in dag object is a shape object, 
		#- need to find all the parent transform objects.
		fnDag = OpenMaya.MFnDagNode(dp)
		#- The number of parents represents the current number of instances.
		self.numInstances = fnDag.parentCount()

		for i in range ( 0, self.numInstances ):
			currentParent = fnDag.parent(i)
			fnParent = OpenMaya.MFnDependencyNode(currentParent)	

			#- Find the rotate plug, figure out which axis the user opted for 
			#- and set the plug to a random direction.
			
			#- TODO: find the plug named 'rotate'
			rotPlug = #...

			#- Acquire a random number deciding which direction the 45 degree should be
			randVal = random.randint(0, 1000)
			if(randVal % 2 == 0):
				randVal = 1
			else:
				randVal = -1
			print "The randVal is %d " % randVal
			sys.stdout.write( '\n' )

			if (self.axis == AXIS_X):
				#- TODO: Get the X plug of the 'rotate' plug
				rotxPlug = #...

				#- retrieve original rotation and store it in member variable "rotations"
				origRot = 0
				#- TODO: Get the plug value
				#...
				self.rotations.append(origRot)

				#- set new rotation
				rot = origRot + randVal * ROTATIONVALUE
				#- TODO: Set the new plug value
				#...
			elif (self.axis == AXIS_Z):
				#- TODO: Get the Z plug of the 'rotate' plug
				rotzPlug = #...

				origRot = 0
				#- TODO: Get the plug value
				#...
				self.rotations.append(origRot)

				rot = origRot + randVal * ROTATIONVALUE
				#- TODO: Set the new plug value
				#...
			else: # AXIS_Y: - by default, rotate around y axis
				- TODO: Get the Y plug of the 'rotate' plug
				rotyPlug = #...

				origRot = 0
				#- TODO: Get the plug value
				#...
				self.rotations.append(origRot)

				rot = origRot + randVal * ROTATIONVALUE
Пример #13
0
    def writeWeights(self, fileName, exclusive):

        # get the current selection
        skinClusterNode = cmds.ls(sl=True, fl=True)
        if len(skinClusterNode) != 0:
            skinClusterNode = skinClusterNode[0]
        else:
            OpenMaya.MGlobal.displayError(
                'Select a skinCluster node to export.')
            return (-1)

        # check if it's a skinCluster
        if cmds.nodeType(skinClusterNode) != 'skinCluster':
            OpenMaya.MGlobal.displayError(
                'Selected node is not a skinCluster.')
            return (-1)

        # get the MFnSkinCluster
        sel = OpenMaya.MSelectionList()
        OpenMaya.MGlobal.getActiveSelectionList(sel)
        skinClusterObject = OpenMaya.MObject()
        sel.getDependNode(0, skinClusterObject)
        # documentation: MFNSkinCluster: https://help.autodesk.com/view/MAYAUL/2018/ENU/?guid=__cpp_ref_class_m_fn_skin_cluster_html
        skinClusterFn = OpenMayaAnim.MFnSkinCluster(skinClusterObject)

        # get the influence objects
        infls = cmds.skinCluster(skinClusterNode, q=True, inf=True)
        if len(infls) == 0:
            OpenMaya.MGlobal.displayError(
                'No influence objects found for skinCluster %s.' %
                skinClusterNode)
            return (-1)

        # get the connected shape node
        shape = cmds.skinCluster(skinClusterNode, q=True, g=True)[0]
        if len(shape) == 0:
            OpenMaya.MGlobal.displayError('No connected shape nodes found.')
            return (-1)

        # get the dag path of the shape node
        cmds.select(shape, r=True)
        sel = OpenMaya.MSelectionList()
        OpenMaya.MGlobal.getActiveSelectionList(sel)
        shapeDag = OpenMaya.MDagPath()
        sel.getDagPath(0, shapeDag)
        # create the geometry iterator
        geoIter = OpenMaya.MItGeometry(shapeDag)

        # create a pointer object for the influence count of the MFnSkinCluster
        infCount = OpenMaya.MScriptUtil()
        infCountPtr = infCount.asUintPtr()
        OpenMaya.MScriptUtil.setUint(infCountPtr, 0)

        value = OpenMaya.MDoubleArray()

        #
        # default export to a single skin weights file
        #
        if not exclusive:
            try:
                weightFile = open(fileName, 'wb')
            except:
                OpenMaya.MGlobal.displayError(
                    'A file error has occured for file \'' + fileName + '\'.')
                return (-1)

            # write all influences and the shape node to the file
            for i in range(0, len(infls), 1):
                weightFile.write(infls[i] + " ")
            weightFile.write(shape + '\n')

            weightFile.write(skinClusterNode + '\n')

            # write the attributes of the skinCluster node to the file
            result = cmds.getAttr(skinClusterNode + ".normalizeWeights")
            weightFile.write('-nw %s ' % result)
            result = cmds.getAttr(skinClusterNode + ".maxInfluences")
            weightFile.write('-mi %s ' % result)
            result = cmds.getAttr(skinClusterNode + ".dropoff")[0][0]
            weightFile.write('-dr %s\n' % result)

            # get the skinCluster weights
            while geoIter.isDone() == False:
                skinClusterFn.getWeights(shapeDag, geoIter.currentItem(),
                                         value, infCountPtr)
                for j in range(0, len(infls)):
                    if value[j] > 0:
                        lineArray = [geoIter.index(), infls[j], j, value[j]]
                        weightFile.write(str(lineArray) + '\n')
                geoIter.next()

            weightFile.close()

        #
        # custom export to individual files
        #
        else:
            cmds.skinCluster(skinClusterNode, e=True, fnw=True)
            dataPath = '%s/%s' % (fileName, skinClusterNode)
            if not os.path.exists(dataPath):
                try:
                    os.makedirs(dataPath)
                except:
                    OpenMaya.MGlobal.displayError(
                        'Unable to create export directory \'' + dataPath +
                        '\'.')
                    return (-1)

            for j in range(0, len(infls)):
                fileName = '%s/%s.bsw' % (dataPath, infls[j])
                try:
                    weightFile = open(fileName, 'wb')
                except:
                    OpenMaya.MGlobal.displayError(
                        'A file error has occured for file \'' + fileName +
                        '\'.')
                    return (-1)

                geoIter.reset()

                while geoIter.isDone() == False:
                    skinClusterFn.getWeights(shapeDag, geoIter.currentItem(),
                                             value, infCountPtr)
                    line = str(geoIter.index()) + ' ' + str(value[j]) + '\n'
                    weightFile.write(line)
                    geoIter.next()

                weightFile.close()

        return (1)
Пример #14
0
    def __getBlendWeights(self, dagPath, components):
        weights = OpenMaya.MDoubleArray()
        self.__mFnScls.getBlendWeights(dagPath, components, weights)

        return weights
Пример #15
0
    def calculateWeights(self, weights, num):
        """
        Calculate the new weights of the removed indices. The new weights are 
        calculated by trying to remove the influence that is active in the 
        tool. Locked influences, normalization are taken into account as they 
        are set on the skin cluster.
        
        :param OpenMaya.MDoubleArray weights: original weights
        :param int num: Amount of influences per vertex
        :return: New weights, new influences
        :rtype: tuple(OpenMaya.MDoubleArray, OpenMaya.MIntArray)
        """
        # variables
        influenceNew = OpenMaya.MIntArray()
        weightsNew = OpenMaya.MDoubleArray()

        # add influences
        for i in range(num):
            influenceNew.append(i)

        # calculate weights
        for i in range(0, weights.length(), num):
            weightsVtx = [weights[i + j] for j in range(num)]
            indexWeight = weights[i + self.index]
            total = sum(weightsVtx)

            # if weight that is trying to be removed is only influence
            # reselect vertex as weights cannot be removed
            if indexWeight == total:
                for w in weightsVtx:
                    weightsNew.append(w)

                continue

            # remove index weight
            factor = 1
            factorLocked = 1

            weightsVtx = [
                weights[i + j] if j != self.index else 0.0 for j in range(num)
            ]

            # normalize weights
            if self.normalizeMode == 1:
                # get total locked weights
                weightsVtxLocked = sum([
                    weights[i + j] for j in range(num)
                    if self.influencesLocked[j]
                ])

                # get total to blend
                total = sum(weightsVtx) - weightsVtxLocked

                # get multiply factor
                if weightsVtxLocked >= 1.0 or total == 0.0:
                    factor = 0
                    factorLocked = 1 / weightsVtxLocked
                else:
                    factor = (1.0 - weightsVtxLocked) / total

            # apply multiply factor
            for j, w in enumerate(weightsVtx):
                if not self.influencesLocked[j]:
                    weightsNew.append(w * factor)
                else:
                    weightsNew.append(w * factorLocked)

        return weightsNew, influenceNew
Пример #16
0
def sang_kraduk(mmddata, chue_nod_poly, khanat, ao_ik):
    print(u'骨を作成中')
    list_chue_nod_kho = []  # ลิสต์เก็บชื่อของโหนดข้อ
    for i, b in enumerate(mmddata.bones):
        # แก้ชื่อข้อต่อให้เป็นโรมาจิ
        chue_kho = romaji(chuedidi(b.name, u'kho%d' % i))
        p = b.position  # ตำแหน่งของข้อต่อ
        mc.select(d=1)
        # สร้างข้อต่อตามตำแหน่งที่กำหนด
        chue_nod_kho = mc.joint(p=[p.x * khanat, p.y * khanat, -p.z * khanat],
                                rad=khanat / 2,
                                n=chue_kho + '_' + chue_nod_poly)

        # เก็บชื่อเดิมไว้เผื่อใช้
        mc.addAttr(chue_nod_kho, ln='namae', nn=u'名前', dt='string')
        mc.setAttr(chue_nod_kho + '.namae',
                   chuedidi(b.name, chue_nod_kho),
                   typ='string')

        # ซ่อนข้อต่อที่ไม่จำเป็นต้องเห็น
        if (b.getIkFlag() or not b.getVisibleFlag()):
            mc.setAttr(chue_nod_kho + '.drawStyle', 2)
        else:
            mc.setAttr(chue_nod_kho + '.drawStyle', 0)

        # ตั้งค่าการจัดวางแกนหมุนของข้อ
        if (b.getLocalCoordinateFlag() or b.getFixedAxisFlag()):
            if (b.getFixedAxisFlag()):
                kaen_x = b.fixed_axis
                kaen_z = cross([0.0, 1.0, 0.0], kaen_x)
            else:
                kaen_x = b.local_x_vector
                kaen_z = b.local_z_vector
            kaen_y = cross(kaen_z, kaen_x)

            array_mun = [
                kaen_x[0], kaen_x[1], -kaen_x[2], 0., kaen_y[0], kaen_y[1],
                -kaen_y[2], 0., kaen_z[0], kaen_z[1], -kaen_z[2], 0., 0., 0.,
                0., 1.
            ]
            matrix_mun = om.MMatrix()  # สร้างเมทริกซ์หมุน
            om.MScriptUtil.createMatrixFromList(array_mun, matrix_mun)
            trans = om.MTransformationMatrix(matrix_mun)
            mum_euler = trans.eulerRotation().asVector()

            mc.setAttr(chue_nod_kho + '.jointOrientX',
                       math.degrees(mum_euler.x))
            mc.setAttr(chue_nod_kho + '.jointOrientY',
                       math.degrees(mum_euler.y))
            mc.setAttr(chue_nod_kho + '.jointOrientZ',
                       math.degrees(mum_euler.z))

        list_chue_nod_kho.append(chue_nod_kho)

    list_mi_ik = []  # ลิสต์ของข้อต่อที่มี IK
    list_chue_nod_nok = []  # ลิสต์ของข้อต่อที่อยู่นอกสุด

    for i, b in enumerate(mmddata.bones):
        chue_nod_kho = list_chue_nod_kho[i]

        if (b.parent_index >= 0):
            # ผูกติดข้อต่อแต่ละข้อเข้าด้วยกัน
            chue_nod_parent = list_chue_nod_kho[b.parent_index]
            mc.connectJoint(chue_nod_kho, chue_nod_parent, pm=1)
        else:
            list_chue_nod_nok.append(chue_nod_kho)

        # แก้ปัญหากรณีที่มุมหมุนของกระดูกมีค่าแปลกๆ (เกิดขึ้นได้อย่างไรยังไม่รู้แน่ชัด)
        if (round(mc.getAttr(chue_nod_kho + '.rx')) == -360.):
            mc.setAttr(chue_nod_kho + '.rx', 0)
        if (round(mc.getAttr(chue_nod_kho + '.ry')) == -360.):
            mc.setAttr(chue_nod_kho + '.ry', 0)
        if (round(mc.getAttr(chue_nod_kho + '.rz')) == -360.):
            mc.setAttr(chue_nod_kho + '.rz', 0)
        if (round(mc.getAttr(chue_nod_kho + '.rx')) % 360 == 180.
                and round(mc.getAttr(chue_nod_kho + '.ry')) % 360 == 180.
                and round(mc.getAttr(chue_nod_kho + '.rz')) % 360 == 180.):
            mc.setAttr(chue_nod_kho + '.rx', 0)
            mc.setAttr(chue_nod_kho + '.ry', 0)
            mc.setAttr(chue_nod_kho + '.rz', 0)

        if (b.getExternalRotationFlag()):
            # ตั้งมุมการหมุนให้ข้อที่เปลี่ยนมุมตามการหมุนของข้ออื่น
            chue_nod_effect = list_chue_nod_kho[
                b.effect_index]  # โหนดข้อที่ส่งผลให้
            x = mc.getAttr(chue_nod_effect + '.jointOrientX')
            y = mc.getAttr(chue_nod_effect + '.jointOrientY')
            z = mc.getAttr(chue_nod_effect + '.jointOrientZ')
            mc.setAttr(chue_nod_kho + '.jointOrientX', x)
            mc.setAttr(chue_nod_kho + '.jointOrientY', y)
            mc.setAttr(chue_nod_kho + '.jointOrientZ', z)

            # ตั้งเอ็กซ์เพรชชันให้ข้อที่เปลี่ยนมุมตามการหมุนของข้ออื่น
            ef = b.effect_factor
            s = '%s.rotateX = %s.rotateX * %s;\n' % (chue_nod_kho,
                                                     chue_nod_effect, ef)
            s += '%s.rotateY = %s.rotateY * %s;\n' % (chue_nod_kho,
                                                      chue_nod_effect, ef)
            s += '%s.rotateZ = %s.rotateZ * %s;\n' % (chue_nod_kho,
                                                      chue_nod_effect, ef)
            mc.expression(s=s,
                          n='expression_%s_%s' %
                          (chue_nod_kho, chue_nod_effect))

        if (b.getExternalTranslationFlag()):
            # ตั้งเอ็กซ์เพรชชันให้ข้อที่เลื่อนตำแหน่งตามตำแหน่งของข้ออื่น
            chue_nod_effect = list_chue_nod_kho[
                b.effect_index]  # โหนดข้อที่ส่งผลให้
            ef = b.effect_factor
            s = '%s.translateX = %s.translateX * %s;\n' % (chue_nod_kho,
                                                           chue_nod_effect, ef)
            s += '%s.translateY = %s.translateY * %s;\n' % (
                chue_nod_kho, chue_nod_effect, ef)
            s += '%s.translateZ = %s.translateZ * %s;\n' % (
                chue_nod_kho, chue_nod_effect, ef)
            mc.expression(s=s,
                          n='expression_%s_%s' %
                          (chue_nod_kho, chue_nod_effect))

        if (b.ik):
            list_mi_ik.append(i)  # เก็บโหนดที่มี IK

    # สร้าง IK ถ้าเลือกไว้ว่าให้สร้าง
    if (ao_ik):
        list_chue_nod_ik = []  # ลิสต์เก็บชื่อโหนด IK
        for i in list_mi_ik:
            b = mmddata.bones[i]
            index_kho = [b.ik.target_index] + [l.bone_index for l in b.ik.link]
            for j in range(0, len(b.ik.link)):
                kho1 = list_chue_nod_kho[index_kho[j]]
                kho2 = list_chue_nod_kho[index_kho[j + 1]]
                mc.select(kho1, kho2)
                chue_nod_ik = mc.ikHandle(n=list_chue_nod_kho[i] + '_IK',
                                          sol='ikRPsolver')[0]
                list_chue_nod_ik.append(chue_nod_ik)

    nod_skin = pm.skinCluster(list_chue_nod_kho, chue_nod_poly, mi=4, tsb=1)

    nod_poly = pm.PyNode(chue_nod_poly)
    path_mesh = om.MDagPath()
    sl = om.MSelectionList()
    sl.add(nod_poly.fullPath())
    sl.getDagPath(0, path_mesh)

    obj_skin = om.MObject()
    sl = om.MSelectionList()
    sl.add(nod_skin.name())
    sl.getDependNode(0, obj_skin)
    fn_skin = oma.MFnSkinCluster(obj_skin)

    sl = om.MSelectionList()
    list_influ = []
    for i, chue_nod_kho in enumerate(list_chue_nod_kho):
        dagpath = om.MDagPath()
        sl.add(pm.PyNode(chue_nod_kho).fullPath())
        sl.getDagPath(i, dagpath)
        idx = fn_skin.indexForInfluenceObject(dagpath)
        list_influ.append(idx)

    n_kho = len(mmddata.bones)
    list_namnak = []
    for v in mmddata.vertices:
        namnak = [0.] * n_kho
        d = v.deform

        if (isinstance(d, pymeshio.pmx.Bdef1)):
            # ส่วนที่ได้รับอิทธิพลจากแค่จุดเดียว
            namnak[d.index0] = 1.
        elif (isinstance(d, (pymeshio.pmx.Bdef2, pymeshio.pmx.Sdef))):
            # ส่วนที่ได้รับอิทธิพลจาก 2 จุด
            namnak[d.index0] += d.weight0
            namnak[d.index1] += 1. - d.weight0
        elif (isinstance(d, pymeshio.pmx.Bdef4)):
            # ส่วนที่ได้รับอิทธิพลจาก 4 จุด
            namnak[d.index0] += d.weight0
            namnak[d.index1] += d.weight1
            namnak[d.index2] += d.weight2
            namnak[d.index3] += 1. - d.weight0 - d.weight1 - d.weight2
        list_namnak.extend(namnak)

    n_chut = len(mmddata.vertices)  # จำนวนจุดยอด
    util = om.MScriptUtil()
    util.createFromList(list_namnak, n_kho * n_chut)
    array_namnak = om.MDoubleArray(util.asDoublePtr(), n_kho * n_chut)

    util = om.MScriptUtil()
    util.createFromList(list_influ, n_kho)
    array_influ = om.MIntArray(util.asIntPtr(), n_kho)

    fn_compo = om.MFnSingleIndexedComponent()
    compo = fn_compo.create(om.MFn.kMeshVertComponent)
    util = om.MScriptUtil()
    util.createFromList(range(n_chut), n_chut)
    index_chut = om.MIntArray(util.asIntPtr(), n_chut)
    fn_compo.addElements(index_chut)
    # ตั้งค่าน้ำหนักของอิทธิพลที่แต่ละข้อมีต่อแต่ละจุดบนโพลิกอน
    fn_skin.setWeights(path_mesh, compo, array_influ, array_namnak, 1)

    for chue_nod_kho in list_chue_nod_kho:
        if (chue_nod_kho not in list_chue_nod_nok):
            mc.rename(chue_nod_kho,
                      chue_nod_kho.replace('_' + chue_nod_poly, ''))
    return list_chue_nod_nok
Пример #17
0
    def setWeights(self, componentList=[]):
        '''
		Apply the stored skinCluster weights to the specified skinCluster.
		@param componentList: The list of components to apply skinCluster weights to.
		@type componentList: str
		'''
        print(
            '!!! - DEPRICATED: skinClusterData.setWeights()! Use loadWeights() method instead - !!!'
        )

        # ==========
        # - Checks -
        # ==========

        # Check SkinCluster
        skinCluster = self._data['name']
        self.verifySkinCluster(skinCluster)

        # Check Geometry
        skinGeo = self._data['affectedGeometry'][0]
        if not mc.objExists(skinGeo):
            raise Exception(
                'SkinCluster geometry "' + skinGeo +
                '" does not exist! Use remapGeometry() to load skinCluster data to a different geometry!'
            )

        # Check Component List
        if not componentList:
            componentList = glTools.utils.component.getComponentStrList(
                skinGeo)
        componentSel = glTools.utils.selection.getSelectionElement(
            componentList, 0)

        # Get Component Index List
        indexList = OpenMaya.MIntArray()
        componentFn = OpenMaya.MFnSingleIndexedComponent(componentSel[1])
        componentFn.getElements(indexList)
        componentIndexList = list(indexList)

        # ===========================
        # - Set SkinCluster Weights -
        # ===========================

        # Build influence index array
        infIndexArray = OpenMaya.MIntArray()
        influenceList = mc.skinCluster(skinCluster, q=True, inf=True)
        [infIndexArray.append(i) for i in range(len(influenceList))]

        # Build master weight array
        wtArray = OpenMaya.MDoubleArray()
        oldWtArray = OpenMaya.MDoubleArray()
        for c in componentIndexList:
            for i in range(len(influenceList)):
                if self._influenceData.has_key(influenceList[i]):
                    wtArray.append(
                        self._influenceData[influenceList[i]]['wt'][c])
                else:
                    wtArray.append(0.0)

        # Get skinCluster function set
        skinFn = glTools.utils.skinCluster.getSkinClusterFn(skinCluster)

        # Set skinCluster weights
        skinFn.setWeights(componentSel[0], componentSel[1], infIndexArray,
                          wtArray, False, oldWtArray)

        # =================
        # - Return Result -
        # =================

        return influenceList
Пример #18
0
    def writeWeights(self, fileName, exclusive):
        # get the current selection
        skinClusterNode = cmds.ls(selection=True, flatten=True)
        if len(skinClusterNode) != 0:
            skinClusterNode = skinClusterNode[0]
        else:
            OpenMaya.MGlobal.displayError(
                "Select a skinCluster node to export.")
            return -1

        # check if it's a skinCluster
        if cmds.nodeType(skinClusterNode) != "skinCluster":
            OpenMaya.MGlobal.displayError(
                "Selected node is not a skinCluster.")
            return -1

        # get the MFnSkinCluster
        sel = OpenMaya.MSelectionList()
        OpenMaya.MGlobal.getActiveSelectionList(sel)
        skinClusterObject = OpenMaya.MObject()
        sel.getDependNode(0, skinClusterObject)
        skinClusterFn = OpenMayaAnim.MFnSkinCluster(skinClusterObject)

        # get the influence objects
        infls = cmds.skinCluster(skinClusterNode, query=True, influence=True)
        if len(infls) == 0:
            OpenMaya.MGlobal.displayError(
                "No influence objects found for skinCluster {}.".format(
                    skinClusterNode))
            return -1

        # get the connected shape node
        shape = cmds.skinCluster(skinClusterNode, query=True, geometry=True)[0]
        if len(shape) == 0:
            OpenMaya.MGlobal.displayError("No connected shape nodes found.")
            return -1

        # get the dag path of the shape node
        cmds.select(shape, replace=True)
        sel = OpenMaya.MSelectionList()
        OpenMaya.MGlobal.getActiveSelectionList(sel)
        shapeDag = OpenMaya.MDagPath()
        sel.getDagPath(0, shapeDag)
        # create the geometry iterator
        geoIter = OpenMaya.MItGeometry(shapeDag)

        # create a pointer object for the influence count of the MFnSkinCluster
        infCount = OpenMaya.MScriptUtil()
        infCountPtr = infCount.asUintPtr()
        OpenMaya.MScriptUtil.setUint(infCountPtr, 0)

        value = OpenMaya.MDoubleArray()

        #
        # default export to a single skin weights file
        #
        if not exclusive:
            try:
                with open(fileName, "w") as fileObj:
                    lines = []
                    nodes = []

                    # write all influences and the shape node to the file
                    for i in range(0, len(infls), 1):
                        nodes.append(infls[i])
                    nodes.append(shape)
                    lines.append(" ".join(nodes))

                    lines.append(skinClusterNode)

                    # write the attributes of the skinCluster node to the file
                    normalize = cmds.getAttr(skinClusterNode +
                                             ".normalizeWeights")
                    maxInfluences = cmds.getAttr(skinClusterNode +
                                                 ".maxInfluences")
                    dropoff = cmds.getAttr(skinClusterNode + ".dropoff")[0][0]
                    lines.append("-nw {} -mi {} -dr {}".format(
                        normalize, maxInfluences, dropoff))

                    # get the skinCluster weights
                    while not geoIter.isDone():
                        skinClusterFn.getWeights(shapeDag,
                                                 geoIter.currentItem(), value,
                                                 infCountPtr)
                        for j in range(0, len(infls)):
                            if value[j] > 0:
                                lineArray = [
                                    geoIter.index(), infls[j], j, value[j]
                                ]
                                lines.append(str(lineArray))
                        geoIter.next()

                    lines.append("")
                    fileObj.write("\n".join(lines))

            except:
                OpenMaya.MGlobal.displayError(
                    "A file error has occurred for file: {}".format(fileName))
                return -1

        #
        # custom export to individual files
        #
        else:
            cmds.skinCluster(skinClusterNode,
                             edit=True,
                             forceNormalizeWeights=True)
            dataPath = "{}/{}".format(fileName, skinClusterNode)
            if not os.path.exists(dataPath):
                try:
                    os.makedirs(dataPath)
                except:
                    OpenMaya.MGlobal.displayError(
                        "Unable to create export directory: {}".format(
                            dataPath))
                    return -1

            for j in range(0, len(infls)):
                fileName = "{}/{}.bsw".format(dataPath, infls[j])
                try:
                    with open(fileName, "w") as fileObj:

                        lines = []
                        while not geoIter.isDone():
                            skinClusterFn.getWeights(shapeDag,
                                                     geoIter.currentItem(),
                                                     value, infCountPtr)
                            line = "{} {}".format(str(geoIter.index()),
                                                  str(value[j]))
                            lines.append(line)
                            geoIter.next()

                        lines.append("")
                        fileObj.write("\n".join(lines))
                except:
                    OpenMaya.MGlobal.displayError(
                        "A file error has occurred for file: {}".format(
                            fileName))
                    return -1

                geoIter.reset()

        return 1
Пример #19
0
 def create_mdouble_array(self, array):
     mdouble_array = OpenMaya.MDoubleArray()
     for x in array:
         mdouble_array.append(x)
     return mdouble_array
Пример #20
0
def fillOptimized():

    sel = cmds.ls(sl=1)
    if not sel:
        print "no mesh selected !"
        return

    obj=sel[0]
    objList = OpenMaya.MSelectionList()
    objList.add(obj)
    path = OpenMaya.MDagPath()
    objList.getDagPath(0,path)
    path.extendToShape()

    closest = OpenMaya.MMeshIntersector()
    closest.create(path.node(),path.inclusiveMatrix())

    try:
        cmds.particleFill(rs=step,maxX=1,maxY=1,maxZ=1,minX=0,minY=0,minZ=0,pd=1.0,cp=True)
    except RuntimeError:
        pass
    
    part = cmds.ls(sl=1)[0]
    partShape = cmds.listRelatives(part,shapes=1)[0]

    nplist  = OpenMaya.MSelectionList()
    nplist.add(partShape)

    npobj   = OpenMaya.MObject()
    nplist.getDependNode(0,npobj)

    npnode  = OpenMaya.MFnDependencyNode(npobj)
    nplug   = npnode.findPlug("position")
    nhdl    = nplug.asMDataHandle()
    ndata   = OpenMaya.MFnVectorArrayData(nhdl.data())

    radii    = OpenMaya.MDoubleArray()
    points   = OpenMaya.MVectorArray() 
    points.copy(ndata.array())

    cmds.delete(part)

    mpom = MPointOnMesh()
    radii_index = {}

    for p in xrange(points.length()):
        vec = points[p]
        point = MPoint(vec)
        closest.getClosestPoint(point, mpom)
        closestPoint = mpom.getPoint()
        radius = point.distanceTo(MPoint(closestPoint))
        radii_index[p] = (vec, point, radius) 


    radii_sorted = sorted(radii_index.itervalues(), key=itemgetter(2), reverse=True)
    newPoints = OpenMaya.MVectorArray()
    newRadii  = OpenMaya.MDoubleArray()
    
    pointsRemain = lambda: len(radii_sorted)

    while pointsRemain():
        print "%s problem points still left..." % pointsRemain()

        vec, p, radius = radii_sorted.pop(0)

        newPoints.append(vec)
        newRadii.append(radius*1.2)

        for i in reversed(xrange(pointsRemain())):

            vec2, p2, otherRadius = radii_sorted[i]

            if p.distanceTo(p2) < (otherRadius + radius):
                del radii_sorted[i]


    #note: the default nParticle creation mode should be set to "points"
            
    part    = cmds.nParticle()[1]
    plist   = OpenMaya.MSelectionList()
    plist.add(part)
    
    newNPObj = OpenMaya.MObject()
    dagPath = OpenMaya.MDagPath()
    plist.getDependNode(0,newNPObj)
    plist.getDagPath(0, dagPath)
    name = dagPath.fullPathName()
    
    newNPNode   = OpenMaya.MFnDependencyNode(newNPObj)
    newPosPlug  = newNPNode.findPlug("position")
    newNPHdl    = newPosPlug.asMDataHandle()
    newposdata  = OpenMaya.MFnVectorArrayData(newNPHdl.data())
    newposdata.set(newPoints)
    newPosPlug.setMObject(newposdata.object())
    
    prt = newNPNode.findPlug("particleRenderType")
    prt.setInt(4)
    
    isg = newNPNode.findPlug("ignoreSolverGravity")
    isg.setInt(1)
    
    tattr   = OpenMaya.MFnTypedAttribute()
    rpp     = tattr.create("radiusPP","rpp",OpenMaya.MFnData.kDoubleArray)
    newNPNode.addAttribute(rpp)
    # rppPlug = newNPNode.findPlug("radiusPP")
    # rpphdl  = rppPlug.asMDataHandle()
    # rppdata = OpenMaya.MFnDoubleArrayData(rpphdl.data())
    # rppdata.set(newRadii)
    # rppPlug.setMObject(rppdata.object())

    fnParticleSys = MFnParticleSystem(newNPObj)
    fnParticleSys.setPerParticleAttribute("radiusPP", newRadii)

        
    print "finished."
Пример #21
0
def get_curve_info(name=False):
    '''
     used to get the curve data from a hand drawn curve in maya - for adding a new curve type to the
     class structure
    '''
    if not name:
        name = cmds.ls(sl=True)[0]

    #    sanity check
    if not cmds.objExists(name):
        print 'object %s not found, aborting' % name
        return

    #    check for nurbs curve shape
    if cmds.nodeType(name) == "nurbsCurve":
        shape = name
    else:
        shpList = cmds.listRelatives(name, s=True)
        shape = shpList[0]

    # use the API to get the curve data
    Mlist = OpenMaya.MSelectionList()
    OpenMaya.MGlobal.getSelectionListByName(shape, Mlist)
    dPath = OpenMaya.MDagPath()
    Mlist.getDagPath(0, dPath)

    crv = OpenMaya.MFnNurbsCurve(dPath)

    degree = crv.degree()

    cvs = OpenMaya.MPointArray()
    knots = OpenMaya.MDoubleArray()

    crv.getCVs(cvs)
    crv.getKnots(knots)

    # print to the script editor for use
    print "DEGREE"
    print degree

    print "CVS"
    length = cvs.length()
    print "["
    for i in range(length):
        print('(' + ` cvs[i][0] ` + ',' + ` cvs[i][1] ` + ',' + ` cvs[i][2] ` +
              '),')
    print "]"

    print "KNOTS"
    print knots


#####################################
#  CODE TESTING
#####################################

#test = ArcControl()
#test = CircleControl()
#test.setColour('green')
#test.set_position([0,1,0], [0,90,0])

#test.add_offset()
#test.hide_rotation()
#test.hide_translation()
#test.hide_scale()
#test.lock_hide("v")
#get_curve_info("curve1")
    mesh_selection_list.getDagPath(0, mesh_dag_path)

    joint_selection_list = om.MSelectionList()
    joint_selection_list.add(joint_object)
    joint_dag_path = om.MDagPath()
    joint_selection_list.getDagPath(0, joint_dag_path)

    skin_selection_list = om.MSelectionList()
    skin_mobject = om.MObject()
    om.MGlobal.getSelectionListByName(skin_object, skin_selection_list)
    skin_selection_list.getDependNode(0, skin_mobject)
    skin_mfn = oma.MFnSkinCluster(skin_mobject)

    # get joint influcenced points and weight values
    components = om.MSelectionList()
    weights = om.MDoubleArray()
    skin_mfn.getPointsAffectedByInfluence(joint_dag_path, components, weights)

    # create cluster
    components_list = list()
    components.getSelectionStrings(components_list)
    cluster_node = cmds.cluster(components_list)

    cluster_selection_list = om.MSelectionList()
    om.MGlobal.getSelectionListByName(cluster_node[0], cluster_selection_list)
    cluster_mobject = om.MObject()
    cluster_selection_list.getDependNode(0, cluster_mobject)
    cluster_mfn = oma.MFnWeightGeometryFilter(cluster_mobject)

    # get geometry's type to cluster weights type
    geo_dag_path = om.MDagPath()
Пример #23
0
    def doSimpleSolver(self):
        '''
        Solve single joint in the x-y plane
        - first it calculates the angle between the handle and the end-effector.
        - then it determines which way to rotate the joint.
        '''

        handle_group = self.handleGroup()  # return a MIkHandleGroup
        handle = handle_group.handle(0)  # return a MObject
        handlePath = OpenMaya.MDagPath.getAPathTo(
            handle)  # Determines the Path to the specified DAG Node
        fnHandle = OpenMayaAnim.MFnIkHandle(
            handlePath)  # argument an Mobject, i supose we use an mdagpath,
        # for possible duplicated objects

        # get the position of the end_effector
        end_effector = OpenMaya.MDagPath()
        fnHandle.getEffector(end_effector)
        tran = OpenMaya.MFnTransform(end_effector)
        effector_position = tran.rotatePivot(OpenMaya.MSpace.kWorld)

        # get the position of the handle
        handle_positions = fnHandle.rotatePivot(OpenMaya.MSpace.kWorld)

        # get the start joint position
        start_joint = OpenMaya.MDagPath()
        fnHandle.getStartJoint(
            start_joint
        )  # start_joint is filled here with the getStartJoint method
        start_tramsform = OpenMaya.MFnTransform(start_joint)
        start_position = start_tramsform.rotatePivot(OpenMaya.MSpace.kWorld)

        # calculate the rotation angle
        v1 = start_position - effector_position
        v2 = start_position - handle_positions
        angle = v1.angle(v2)

        # -------- Figure out which way to rotate --------
        #
        #  define two vectors U and V as follows
        #  U   =   EndEffector(E) - StartJoint(S)
        #  N   =   Normal to U passing through EndEffector
        #
        #  Clip handle_position to half-plane U to determine the region it
        #  lies in. Use the region to determine  the rotation direction.
        #
        #             U
        #             ^              Region      Rotation
        #             |  B
        #            (E)---N            A          C-C-W
        #         A   |                 B           C-W
        #             |  B
        #             |
        #            (S)
        #
        rot = 0.0  # Rotation about z-axis

        # U and N define a half-plane to clip the handle against
        u = effector_position - start_position
        u.normalize()

        # Get a normal to U
        zAxis = OpenMaya.MVector(0.0, 0.0, 1.0)
        N = u ^ zAxis  # cross product
        N.normalize()

        # P is the handle position vector
        P = handle_positions - effector_position

        # Determine the rotation direction
        PdotN = P[0] * N[0] + P[1] * N[1]
        if PdotN < 0:
            rot = angle  # counter-clockwise
        else:
            rot = -1.0 * angle  # clockwise

        # get and set the Joint Angles
        jointAngles = OpenMaya.MDoubleArray()
        try:
            self._getJointAngles(jointAngles)  # here fill jointAngles
        except:
            # getting angles failed, do nothing
            pass
        else:
            jointAngles.set(jointAngles[0] + rot,
                            0)  # set rotation in the array
            self._setJointAngles(jointAngles)  # set joint rotation
    def testCreases(self):

        cortexCube = IECoreScene.MeshPrimitive.createBox(
            imath.Box3f(imath.V3f(-1), imath.V3f(1)))

        cornerIds = [5]
        cornerSharpnesses = [10.0]

        cortexCube.setCorners(IECore.IntVectorData(cornerIds),
                              IECore.FloatVectorData(cornerSharpnesses))

        creaseLengths = [3, 2]
        creaseIds = [1, 2, 3, 4, 5]  # note that these are vertex ids
        creaseSharpnesses = [1, 5]

        cortexCube.setCreases(IECore.IntVectorData(creaseLengths),
                              IECore.IntVectorData(creaseIds),
                              IECore.FloatVectorData(creaseSharpnesses))

        converter = IECoreMaya.ToMayaObjectConverter.create(cortexCube)
        transform = maya.cmds.createNode("transform")
        self.assertTrue(converter.convert(transform))

        mayaMesh = maya.cmds.listRelatives(transform, shapes=True)[0]

        l = OpenMaya.MSelectionList()
        l.add(mayaMesh)
        p = OpenMaya.MDagPath()
        l.getDagPath(0, p)

        fnMesh = OpenMaya.MFnMesh(p)

        # Test corners

        cornerIds = OpenMaya.MUintArray()
        cornerSharpnesses = OpenMaya.MDoubleArray()
        fnMesh.getCreaseVertices(cornerIds, cornerSharpnesses)

        testIds = OpenMaya.MUintArray()
        testIds.append(5)
        self.assertEqual(cornerIds, testIds)

        testSharpnesses = OpenMaya.MFloatArray()
        testSharpnesses.append(10)
        self.assertEqual(cornerSharpnesses, testSharpnesses)

        # Test edges

        edgeIds = OpenMaya.MUintArray()
        edgeSharpnesses = OpenMaya.MDoubleArray()
        fnMesh.getCreaseEdges(edgeIds, edgeSharpnesses)

        util = OpenMaya.MScriptUtil()

        result = []
        for edgeId, sharpness in zip(edgeIds, edgeSharpnesses):

            edgeVertices = util.asInt2Ptr()
            fnMesh.getEdgeVertices(edgeId, edgeVertices)

            result.append((util.getInt2ArrayItem(edgeVertices, 0, 1),
                           util.getInt2ArrayItem(edgeVertices, 0,
                                                 0), sharpness))

        # we compare sets because maya reorders by edge index
        self.assertEqual(set(result),
                         set([(1, 2, 1.0), (2, 3, 1.0), (4, 5, 5.0)]))
Пример #25
0
def setBlendWeights(skinCls, dagPath, components, dataDic):
    blendWeights = OpenMaya.MDoubleArray(len(dataDic['blendWeights']))
    for i, w in enumerate(dataDic['blendWeights']):
        blendWeights.set(w, i)
    skinCls.__apimfn__().setBlendWeights(dagPath, components, blendWeights)
Пример #26
0
def create_anim_curve_node(
        times,
        values,
        node_attr=None,
        tangent_in_type=OpenMayaAnim.MFnAnimCurve.kTangentGlobal,
        tangent_out_type=OpenMayaAnim.MFnAnimCurve.kTangentGlobal,
        anim_type=OpenMayaAnim.MFnAnimCurve.kAnimCurveTL,
        undo_cache=None):
    """
    Create an animCurve using the Maya API


    :param times: Time values for the animCurve
    :type times: list

    :param values: Values for the animCurve.
    :type values: list

    :param node_attr: The 'plug' to connect the animCurve to.
    :type node_attr: str

    :param tangent_in_type: The "in" tangent type for keyframes.
    :param tangent_out_type: The "out" tangent type for keyframes.
    :param anim_type: The type of animation curve node.
    :param undo_cache: The Maya AnimCurve Undo Cache data structure.
    :return:
    """
    if not isinstance(times, list):
        raise ValueError('times must be a list or sequence type.')
    if not isinstance(values, list):
        raise ValueError('times must be a list or sequence type.')
    if len(times) == 0:
        raise ValueError('times must have 1 or more values.')
    if len(values) == 0:
        raise ValueError('values must have 1 or more values.')
    if len(times) != len(values):
        raise ValueError('Number of times and values does not match.')

    # create anim curve
    animfn = OpenMayaAnim.MFnAnimCurve()
    if node_attr is None:
        animCurve = animfn.create(anim_type)
    else:
        # Get the plug to be animated.
        dst_plug = utils.get_as_plug(node_attr)

        objs = OpenMaya.MObjectArray()
        find = OpenMayaAnim.MAnimUtil.findAnimation(dst_plug, objs)
        if find is True and objs.length() > 0:
            animfn = OpenMayaAnim.MFnAnimCurve(objs[0])
        else:
            animfn = OpenMayaAnim.MFnAnimCurve()
            animfn.create(dst_plug)

    # Copy the times into an MTimeArray and the values into an MDoubleArray.
    time_array = OpenMaya.MTimeArray()
    value_array = OpenMaya.MDoubleArray()
    for time, value in zip(times, values):
        time_array.append(OpenMaya.MTime(time, OpenMaya.MTime.uiUnit()))
        value_array.append(value)

    # force a default undo cache
    if not undo_cache:
        undo_cache = OpenMayaAnim.MAnimCurveChange()

    # Add the keys to the animCurve.
    animfn.addKeys(
        time_array,
        value_array,
        tangent_in_type,
        tangent_out_type,
        False,  # overwrite any keys that get in our way
        undo_cache)
    return animfn
Пример #27
0
 def get_blend_weights(self, dag_path, components):
     weights = om.MDoubleArray()
     self.fn.getBlendWeights(dag_path, components, weights)
     self.data['blendWeights'] = [
         weights[i] for i in xrange(weights.length())
     ]
Пример #28
0
    def buildData(self, surface, worldSpace=False):
        '''
		Build NurbsSurfaceData class.
		@param surface: Surface to build data from
		@type surface: str
		'''
        # ==========
        # - Checks -
        # ==========

        # Check Surface
        if not glTools.utils.surface.isSurface(surface):
            raise Exception('Object "' + surface +
                            '" is not a vaild NURBS surface node!')

        # World Space
        space = OpenMaya.MSpace.kObject
        if worldSpace: space = OpenMaya.MSpace.kWorld

        # ==============
        # - Build Data -
        # ==============

        # Start timer
        timer = mc.timerX()

        # Get basic surface info
        self._data['name'] = surface

        # Get Surface Function Class
        surfaceFn = glTools.utils.surface.getSurfaceFn(surface)

        # Get Surface Degree and Form
        self._data['degreeU'] = surfaceFn.degreeU()
        self._data['degreeV'] = surfaceFn.degreeV()
        self._data['formU'] = int(surfaceFn.formInU())
        self._data['formV'] = int(surfaceFn.formInV())

        # Get Surface Knots
        knotsUarray = OpenMaya.MDoubleArray()
        knotsVarray = OpenMaya.MDoubleArray()
        surfaceFn.getKnotsInU(knotsUarray)
        surfaceFn.getKnotsInV(knotsVarray)
        self._data['knotsU'] = list(knotsUarray)
        self._data['knotsV'] = list(knotsVarray)

        # Get Control Vertices
        cvArray = OpenMaya.MPointArray()
        surfaceFn.getCVs(cvArray, space)
        self._data['cv'] = [(cvArray[i].x, cvArray[i].y, cvArray[i].z)
                            for i in range(cvArray.length())]

        # =================
        # - Return Result -
        # =================

        # Print timer result
        buildTime = mc.timerX(st=timer)
        print('NurbsSurfaceData: Data build time for surface "' + surface +
              '": ' + str(buildTime))

        return self._data['name']
Пример #29
0
def ExportMesh(filepath, meshShapedagPath):
    meshFn = OpenMaya.MFnMesh(meshShapedagPath)
    meshIntersector = OpenMaya.MMeshIntersector()
    meshIntersector.create(meshShapedagPath.node())

    faceIdList = []
    baryCoordList = []

    points = OpenMaya.MPointArray()
    meshFn.getPoints(points, OpenMaya.MSpace.kWorld)

    normals = OpenMaya.MFloatVectorArray()
    meshFn.getVertexNormals(False, normals, OpenMaya.MSpace.kWorld)

    triangleCounts = OpenMaya.MIntArray()
    triangleVertexIndices = OpenMaya.MIntArray(
    )  # the size of this array is three times of the number of total triangles
    meshFn.getTriangles(triangleCounts, triangleVertexIndices)

    #-------------------------
    # Get skin cluster object
    #-------------------------
    skinClusterName = ''
    mesh_shape_name = meshFn.name()
    skinClusters = cmds.listHistory(mesh_shape_name)
    skinClusters = cmds.ls(skinClusters, type="skinCluster")
    if skinClusters:
        skinClusterName = skinClusters[0]
    else:
        cmds.warning('No skin cluster found on ' + mesh_shape_name)
        return

    #print skinClusterName

    # get the MFnSkinCluster using skinClusterName
    selList = OpenMaya.MSelectionList()
    selList.add(skinClusterName)
    skinClusterNode = OpenMaya.MObject()
    selList.getDependNode(0, skinClusterNode)
    skinFn = OpenMayaAnim.MFnSkinCluster(skinClusterNode)

    dagPaths = MDagPathArray()
    skinFn.influenceObjects(dagPaths)

    # influence object is a joint
    influenceObjectsNames = []

    # get joint names
    for i in range(dagPaths.length()):
        influenceName = dagPaths[i].partialPathName()
        influenceObjectsNames.append(
            influenceName)  # Need to remove namespace?

    skinMeshes = cmds.skinCluster(skinClusterName, query=1, geometry=1)
    geoIter = OpenMaya.MItGeometry(meshShapedagPath)
    infCount = OpenMaya.MScriptUtil()
    infCountPtr = infCount.asUintPtr()
    numVertices = geoIter.count()

    weightArray = [
        0
    ] * TRESSFX_MAX_INFLUENTIAL_BONE_COUNT * numVertices  # joint weight array for all vertices. Each vertex will have TRESSFX_MAX_INFLUENTIAL_BONE_COUNT  weights.
    # It is initialized with zero for empty weight in case there are less weights than TRESSFX_MAX_INFLUENTIAL_BONE_COUNT .
    jointIndexArray = [
        -1
    ] * TRESSFX_MAX_INFLUENTIAL_BONE_COUNT * numVertices  # joint index array for all vertices. It is initialized with -1 for an empty element in case
    # there are less weights than TRESSFX_MAX_INFLUENTIAL_BONE_COUNT .

    # collect bone weights for all vertices in the mesh
    index = 0

    progressBar = ProgressBar('Collect data', numVertices)

    while geoIter.isDone() == False:
        weights = OpenMaya.MDoubleArray()
        skinFn.getWeights(meshShapedagPath, geoIter.currentItem(), weights,
                          infCountPtr)

        weightJointIndexPairs = []

        for i in range(len(weights)):
            pair = WeightJointIndexPair()
            pair.weight = weights[i]
            pair.joint_index = i
            weightJointIndexPairs.append(pair)

        weightJointIndexPairs.sort()

        a = 0

        for j in range(
                min(len(weightJointIndexPairs),
                    TRESSFX_MAX_INFLUENTIAL_BONE_COUNT)):
            weightArray[index * TRESSFX_MAX_INFLUENTIAL_BONE_COUNT +
                        a] = weightJointIndexPairs[j].weight
            jointIndexArray[index * TRESSFX_MAX_INFLUENTIAL_BONE_COUNT +
                            a] = weightJointIndexPairs[j].joint_index
            a += 1

        index += 1
        progressBar.Increment()
        geoIter.next()

    progressBar.Kill()

    #----------------------------------------------------------
    # We collected all necessary data. Now save them in file.
    #----------------------------------------------------------
    totalProgress = points.length() + triangleVertexIndices.length() / 3 + len(
        influenceObjectsNames)
    progressBar = ProgressBar('Export collision mesh', totalProgress)

    f = open(filepath, "w")
    f.write("# TressFX collision mesh exported by TressFX Exporter in Maya\n")

    # Write all bone (joint) names
    f.write("numOfBones %g\n" % (len(influenceObjectsNames)))
    f.write("# bone index, bone name\n")
    for i in range(len(influenceObjectsNames)):
        f.write("%d %s\n" % (i, influenceObjectsNames[i]))
        progressBar.Increment()

    # write vertex positions and skinning data
    f.write("numOfVertices %g\n" % (points.length()))
    f.write(
        "# vertex index, vertex position x, y, z, normal x, y, z, joint index 0, joint index 1, joint index 2, joint index 3, weight 0, weight 1, weight 2, weight 3\n"
    )
    for vertexIndex in xrange(points.length()):
        point = points[vertexIndex]
        normal = normals[vertexIndex]
        weightJointIndexPairs = GetSortedWeightsFromOneVertex(
            TRESSFX_MAX_INFLUENTIAL_BONE_COUNT, vertexIndex, jointIndexArray,
            weightArray)
        f.write(
            "%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g\n" %
            (vertexIndex, point.x, point.y, point.z, normal.x, normal.y,
             normal.z, weightJointIndexPairs[0].joint_index,
             weightJointIndexPairs[1].joint_index,
             weightJointIndexPairs[2].joint_index,
             weightJointIndexPairs[3].joint_index,
             weightJointIndexPairs[0].weight, weightJointIndexPairs[1].weight,
             weightJointIndexPairs[2].weight, weightJointIndexPairs[3].weight))
        progressBar.Increment()

    # write triangle face indices
    f.write("numOfTriangles %g\n" % (triangleVertexIndices.length() / 3))
    f.write(
        "# triangle index, vertex index 0, vertex index 1, vertex index 2\n")
    for i in range(triangleVertexIndices.length() / 3):
        f.write("%g %d %d %d\n" % (i, triangleVertexIndices[i * 3 + 0],
                                   triangleVertexIndices[i * 3 + 1],
                                   triangleVertexIndices[i * 3 + 2]))
        progressBar.Increment()

    f.close()
    progressBar.Kill()
    return
Пример #30
0
    def calculateWeights(self, value, weightsO, weightsC, numI, numC):
        """
        Calculate the new weights of the parsed index. The new weights are 
        calculated by blending the weights of the connected vertices, this is 
        done with the factor of the value. The value is parsed by the context
        and can range from 0-1 depending on where the point is in the paint 
        brush. Locked influences, normalization and maintaining maximum
        influences are taken into account as they are set on the skin cluster.
        
        :param float value: Blend factor
        :param OpenMaya.MDoubleArray weightsO: Weights of original
        :param OpenMaya.MDoubleArray weightsC: Weights of connected
        :param int numI: Influences of original
        :param int numC: Influences of connected
        :return: New weights, new influences
        :rtype: tuple(OpenMaya.MDoubleArray, OpenMaya.MIntArray)
        """
        # weight variables
        weightsNew = OpenMaya.MDoubleArray()
        influenceNew = OpenMaya.MIntArray()

        # blend weights
        for i in range(numI):
            influenceNew.append(i)
            weightsNew.append(0.0)

            # if influence is locked dont change value
            if self.influencesLocked[i]:
                weightsNew[i] = weightsO[i]
                continue

            # blend weights with connected vertices
            for j in range(i, len(weightsC), numI):
                w = ((weightsO[i] / numC) *
                     (1 - value)) + ((weightsC[j] / numC) * value)
                weightsNew[i] += w

        # force max influences by removing excess weights
        if self.maintainMaxInfluences:
            weights = zip(weightsNew, influenceNew)
            excess = sorted(weights, reverse=True)[self.maxInfluences:]
            for e in excess:
                weightsNew[e[1]] = 0.0

        # normalize weights to one
        if self.normalizeMode == 1:
            # get total locked weights
            lockedTotal = sum([
                weightsNew[i] for i in range(weightsNew.length())
                if self.influencesLocked[i]
            ])

            # get total to blend
            total = sum(weightsNew) - lockedTotal

            # get multiply factor
            if lockedTotal >= 1.0 or total == 0.0:
                factor = 0
            else:
                factor = (1.0 - lockedTotal) / total

            # apply multiply factor
            for i in range(weightsNew.length()):
                if self.influencesLocked[i]:
                    continue

                weightsNew[i] = weightsNew[i] * factor

        return weightsNew, influenceNew