def _exportBones(self, mesh, dagPath):
        options = self.options.copy()
        if options['bones']:
            # export skeleton skinIndices skinWeights and animation

            for skin in self.skins:
                skinMeshes = mc.skinCluster(skin, q=1, g=1)
                if mesh in skinMeshes:
                    selectionList = MSelectionList()
                    selectionList.add(skin)
                    node = MObject()
                    selectionList.getDependNode(0, node)
                    skinClusterNode = omAnim.MFnSkinCluster(node)
                    infs = MDagPathArray()
                    numInfs = skinClusterNode.influenceObjects(infs)
                    skinPath = MDagPath()
                    index = 0
                    skinClusterNode.indexForOutputConnection(index)
                    skinClusterNode.getPathAtIndex(index, skinPath)
                    geom = MItGeometry(dagPath)
                    vertecies = geom.count()
                    inflNames = []
                    for counter in range(0, numInfs, 1):
                        infName = infs[counter].partialPathName()
                        inflNames.append(infName)
                    firstJoint = inflNames[0]
                    while mc.listRelatives(firstJoint, p=True):
                        parent = mc.listRelatives(firstJoint, p=True)
                        firstJoint = parent[0]
                    if len(self.bones) == 0:
                        self.saveJoints(firstJoint, -1)
                    elif firstJoint != self.bones[0].name:
                        self.saveJoints(firstJoint, -1)
                    jointIndices = []
                    for n in range(0, len(inflNames), 1):
                        for i in range(0, len(self.bones), 1):
                            if self.bones[i].name == inflNames[n]:
                                jointIndices.append(i)
                    wts = MDoubleArray()
                    infCount = MScriptUtil()
                    ccc = infCount.asUintPtr()
                    component = MObject()

                    while not geom.isDone():
                        component = geom.component()
                        skinClusterNode.getWeights(skinPath, component, wts,
                                                   ccc)
                        vertInfluences = []
                        vertWeightInfo = []
                        if len(jointIndices):
                            for i in range(0, (len(wts) / len(jointIndices)),
                                           1):
                                vertInfluences = []
                                for n in range(0, len(jointIndices), 1):
                                    jointIndex = jointIndices[n]
                                    vertInfluences.append(
                                        VertInfluence(wts[n], jointIndex))
                                vertInfluences = sorted(
                                    vertInfluences,
                                    key=lambda vertInfluence: vertInfluence.
                                    weight)
                                vertInfluences.reverse()
                                vertWeightTotal = 0
                                for n in range(0, MAX_INFLUENCES, 1):
                                    weight = _round8(vertInfluences[n].weight)
                                    #if this is the last influence the next influence will take the remainder.
                                    if n == MAX_INFLUENCES - 1 or vertInfluences[
                                            n + 1].weight == 0:
                                        weight = vertInfluences[
                                            n].weight = 1 - vertWeightTotal
                                    vertWeightTotal += weight
                                    self.skinIndices.append(
                                        vertInfluences[n].jointIndex)
                                    self.skinWeights.append(float(weight))

                                    #DEBUG print 'component = ' + str(component) + ' index = ' + str(vertInfluences[n].jointIndex) + ' weight = ' + str(weight)
                        geom.next()
Exemplo n.º 2
0
 def setSkinCluster(self, skinClusterName):
     self.skinCluster = skinClusterName
     self.fn = oma.MFnSkinCluster(Utils.getMObjectForNode(skinClusterName))
     return self
Exemplo n.º 3
0
def exportSkinWeight(exportPath, meshes, namespace=False):
    '''
    Args:
        exportPath: The file path where a json file is saved.
        meshes: A list of mesh nodes.
        namespace: True to export with namespace. False to export without namespace.

    Returns: True if export succeeds. False if export fails.

    Skin file data formatting:
    # {
        #     "mesh_name": {
        #         "weights": {
        #             "vert id": {
        #                 "influence id": weight,
        #                 "influence id": weight
        #             }
        #         },
        #         "infs": [inf1, inf2, inf3, inf4, ...],
        #         "skinCluster": skinCluster_name
        #     }
        # }
    '''
    data = {}
    if not meshes:
        LOG.error('Meshes input {0} is not valid.'.format(meshes))
        return False

    for mesh in meshes:
        skinCluster = getSkinCluster(mesh)
        skinNorm = cmds.getAttr('%s.normalizeWeights' % skinCluster)
        deformNorm = cmds.getAttr('%s.deformUserNormals' % skinCluster)

        # get the MFnSkinCluster for clusterName
        selList = om.MSelectionList()
        selList.add(skinCluster)
        clusterNode = om.MObject()
        selList.getDependNode(0, clusterNode)
        skinFn = oma.MFnSkinCluster(clusterNode)

        # get the MDagPath for all influence
        infDags = om.MDagPathArray()
        skinFn.influenceObjects(infDags)

        infIds = {}
        infs = []
        unique = True
        for i in xrange(infDags.length()):
            infPath = infDags[i].partialPathName()
            if '|' in infPath:
                LOG.warning(
                    'Influence of {}: "{}" is not have a unique name.'.format(
                        mesh, infDags[i].fullPathName()))
                unique = False
            infId = int(skinFn.indexForInfluenceObject(infDags[i]))
            infIds[infId] = i
            infs.append(infPath)
        if not unique:
            LOG.warning(
                '{} skincluster export is skipped. Please make sure all influence names are unique'
                .format(mesh))
            continue

        # get the MPlug for the weightList and weights attributes
        wlPlug = skinFn.findPlug('weightList')
        wPlug = skinFn.findPlug('weights')
        wlAttr = wlPlug.attribute()
        wAttr = wPlug.attribute()
        wInfIds = om.MIntArray()

        # progressBar visualization
        total = wlPlug.numElements()
        progressBar = QtWidgets.QProgressBar()
        progressBar.setStyleSheet(STYLESHEET)
        progressBar.setMinimumSize(QtCore.QSize(450, 25))
        progressBar.setMinimum(1)
        progressBar.setMaximum(total)
        progressBar.setWindowTitle('Exporting skincluster: {}'.format(mesh))
        progressBar.show()
        completed = 0

        weights = {}
        for vId in xrange(wlPlug.numElements()):
            vWeights = {}
            # tell the weights attribute which vertex id it represents
            wPlug.selectAncestorLogicalIndex(vId, wlAttr)

            # get the indice of all non-zero weights for this vert
            wPlug.getExistingArrayAttributeIndices(wInfIds)

            # create a copy of the current wPlug
            infPlug = om.MPlug(wPlug)

            completed += 1
            progressBar.setValue(completed)
            for infId in wInfIds:
                # tell the infPlug it represents the current influence id
                infPlug.selectAncestorLogicalIndex(infId, wAttr)

                # add this influence and its weight to this verts weights
                try:
                    vWeights[infIds[infId]] = infPlug.asDouble()
                except KeyError:
                    # assumes a removed influence
                    pass
            weights[vId] = vWeights

        if namespace:
            meshName = mesh
        else:
            meshName = mesh.split(':')[-1]

        data[meshName] = {
            'weights': weights,
            'infs': infs,
            'skinCluster': skinCluster,
            'nw': skinNorm,
            'deformUserNormals': deformNorm
        }

    with open(exportPath, 'w') as outfile:
        try:
            json.dump(data, outfile, sort_keys=True, indent=4)
            LOG.info('Exported skin weights for mesh {} to {}'.format(
                ' '.join(meshes), exportPath))
            return True
        except:
            LOG.error(
                'Unable to export skinWeight data to {0}.'.format(exportPath))
            return False
    # input object to dag path
    mesh_selection_list = om.MSelectionList()
    mesh_selection_list.add(mesh_object)
    mesh_dag_path = om.MDagPath()
    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)
Exemplo n.º 5
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
Exemplo n.º 6
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!')
Exemplo n.º 7
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
Exemplo n.º 8
0
def bSkinObject(objectName, fileJoints, weights):

    if not cmds.objExists(objectName):
        print objectName, " doesn't exist - skipping. "
        return

    it = OpenMaya.MItDependencyNodes(OpenMaya.MFn.kJoint)

    # quick check if all the joints are in scene
    #
    allInfluencesInScene = True
    sceneJointTokens = []

    for jointIndex in range(len(fileJoints)):
        jointHere = False
        it = OpenMaya.MItDependencyNodes(OpenMaya.MFn.kJoint)
        while not it.isDone():
            sceneJointTokens = str(
                OpenMaya.MFnDagNode(it.item()).fullPathName()).split('|')
            if str(fileJoints[jointIndex]) == str(
                    sceneJointTokens[len(sceneJointTokens) - 1]):
                jointHere = True

            it.next()

        if not jointHere:
            allInfluencesInScene = False
            print 'missing influence: ', fileJoints[jointIndex]

    if not allInfluencesInScene:
        print objectName, " can't be skinned because of missing influences."
        return

    # create some arrays
    #
    allJointsHere = False
    totalJointsCount = len(fileJoints)
    fileJointsMapArray = range(len(fileJoints))
    objectEmptyJoints = []

    # let's check if there's already a skinCluster, let's try to use that - if it contains all the needed joints
    #
    skinCluster = bFindSkinCluster(objectName)
    if type(skinCluster) != type(True):
        fnSkinCluster = OpenMayaAnim.MFnSkinCluster(skinCluster)
        influentsArray = OpenMaya.MDagPathArray()
        infCount = fnSkinCluster.influenceObjects(influentsArray)

        influenceStringArray = []
        for i in range(infCount):
            influenceStringArray.append(
                OpenMaya.MFnDagNode(influentsArray[i]).name())

        allJointsHere = True
        for joint in fileJoints:
            if joint not in influenceStringArray:
                print 'missing a joint (', joint, ', ..)'
                allJointsHere = False
                break

        if not allJointsHere:
            maya.mel.eval("DetachSkin " + objectName)
        else:
            objectFoundJointsInFile = [False] * len(influenceStringArray)

            for i in range(len(fileJoints)):
                for k in range(len(influenceStringArray)):
                    if fileJoints[i] == influenceStringArray[k]:
                        fileJointsMapArray[i] = k
                        objectFoundJointsInFile[k] = True

            for i in range(len(influenceStringArray)):
                if not objectFoundJointsInFile[i]:
                    objectEmptyJoints.append(i)
            totalJointsCount = len(fileJointsMapArray) + len(objectEmptyJoints)

            #print 'jointMapArray: ', fileJointsMapArray

    if not allJointsHere:
        cmd = "select "
        for i in range(len(fileJoints)):
            cmd += " " + fileJoints[i]

        cmd += " " + objectName
        maya.mel.eval(cmd)

        maya.mel.eval("skinCluster -tsb -mi 10")
        maya.mel.eval("select `listRelatives -p " + objectName + "`")
        maya.mel.eval("refresh")
        #maya.mel.eval("undoInfo -st 1")

        skinCluster = bFindSkinCluster(objectName)

    fnSkinCluster = OpenMayaAnim.MFnSkinCluster(skinCluster)
    influentsArray = OpenMaya.MDagPathArray()
    fnSkinCluster.influenceObjects(influentsArray)

    bSkinPath = OpenMaya.MDagPath()
    fnSkinCluster.getPathAtIndex(fnSkinCluster.indexForOutputConnection(0),
                                 bSkinPath)

    weightStrings = []
    vertexIter = OpenMaya.MItGeometry(bSkinPath)

    weightDoubles = OpenMaya.MDoubleArray()

    singleIndexed = True
    vtxComponents = OpenMaya.MObject()
    fnVtxComp = OpenMaya.MFnSingleIndexedComponent()
    fnVtxCompDouble = OpenMaya.MFnDoubleIndexedComponent()

    if bSkinPath.node().apiType() == OpenMaya.MFn.kMesh:
        vtxComponents = fnVtxComp.create(OpenMaya.MFn.kMeshVertComponent)
    elif bSkinPath.node().apiType() == OpenMaya.MFn.kNurbsSurface:
        singleIndexed = False
        vtxComponents = fnVtxCompDouble.create(
            OpenMaya.MFn.kSurfaceCVComponent)
    elif bSkinPath.node().apiType() == OpenMaya.MFn.kNurbsCurve:
        vtxComponents = fnVtxComp.create(OpenMaya.MFn.kCurveCVComponent)

    # nurbs curves..
    #
    counterValue = 0
    if not singleIndexed:
        currentU = 0
        currentV = 0

        cvsU = OpenMaya.MFnNurbsSurface(bSkinPath.node()).numCVsInU()
        cvsV = OpenMaya.MFnNurbsSurface(bSkinPath.node()).numCVsInV()
        formU = OpenMaya.MFnNurbsSurface(bSkinPath.node()).formInU()
        formV = OpenMaya.MFnNurbsSurface(bSkinPath.node()).formInV()

        if formU == 3:
            cvsU -= 3
        if formV == 3:
            cvsV -= 3

    # go through all vertices and append to the weightDoubles array
    #
    vertexIter = OpenMaya.MItGeometry(bSkinPath)
    while not vertexIter.isDone():
        weightStrings = []
        if singleIndexed:
            fnVtxComp.addElement(counterValue)
        else:
            fnVtxCompDouble.addElement(currentU, currentV)
            currentV += 1
            if currentV >= cvsV:
                currentV = 0
                currentU += 1

        weightStrings = weights[counterValue].split(' ')
        for i in range(len(weightStrings)):
            weightDoubles.append(float(weightStrings[i]))
        for i in range(len(objectEmptyJoints)):
            weightDoubles.append(0)

        counterValue += 1
        vertexIter.next()

    # createing the influence Array
    #
    mayafileJointsMapArray = OpenMaya.MIntArray()
    for i in range(len(fileJointsMapArray)):
        mayafileJointsMapArray.append(fileJointsMapArray[i])
    for i in range(len(objectEmptyJoints)):
        mayafileJointsMapArray.append(objectEmptyJoints[i])

    # set the weights
    #
    fnSkinCluster.setWeights(bSkinPath, vtxComponents, mayafileJointsMapArray,
                             weightDoubles, 0)
    def export_skeletons(self):
        dag_it = om.MItDependencyNodes(om.MFn.kSkinClusterFilter)
        while not dag_it.isDone():
            obj = dag_it.thisNode()
            joints = om.MDagPathArray()
 
            skin_fn = omanim.MFnSkinCluster(obj)
            num_joints = skin_fn.influenceObjects(joints)
 
 
            # Loop through joints and look in block cache whether
            # a skeleton for this joint has been exported. If not,
            # we will ignore this binding altogether.
            skel = None
            #print('found skin cluster for %s!' % skel)
            for i in range(num_joints):
                #print('affected joint: %s' % joints[i].fullPathName())
                skel = self.block_cache.get(self.get_skeleton_root(joints[i].fullPathName()))
                if skel is not None:
                    break
 
            # Skeleton was found
            if skel is not None:
                #print('found skeleton in cache!')
                #print('num joints: %d' % num_joints)
 
                # Loop through meshes that are influenced by this
                # skeleton, and add weight stream to their mesh data
                num_geoms = skin_fn.numOutputConnections()
                #print('num geoms: %d' % num_geoms)
                for i in range(num_geoms):
                    skin_path = om.MDagPath()
                    skin_fn.getPathAtIndex(i, skin_path)
                    vert_it = om.MItMeshVertex(skin_path)
 
                    #print('skin obj: %s' % skin_path.fullPathName())
 
                    # Check whether a mesh data for this geometry has
                    # been added to the block cache. If not, bindings
                    # for this mesh can be ignored.
                    md = self.block_cache.get(self.get_name(skin_path.fullPathName()))
                    if md is not None:
                        #print('found mesh in cache!')
                        weight_data = []
                        index_data = []

                        self.has_skelanim = True
 
                        while not vert_it.isDone():
                            comp = vert_it.currentItem()
                            weights = om.MDoubleArray()
                            weight_objs = []
 
                            #script_util = om.MScriptUtil()
                            for ii in range(num_joints):
                                skin_fn.getWeights(skin_path, comp, ii, weights)
                                joint_name = joints[ii].fullPathName()
                                joint_idx = self.joint_indices[joint_name.split('|')[-1]]
                                weight_objs.append( (joint_idx, weights[0]) )
 
                            def comp_weight_objs(wo0, wo1):
                                if wo0[1] > wo1[1]: return -1
                                else: return 1
 
                            weight_objs.sort(comp_weight_objs)
 
                            # Normalize top weights
                            weight_objs = weight_objs[0:self.joints_per_vert]
                            sum_obj = reduce(lambda w0,w1: (0, w0[1]+w1[1]), weight_objs)
                            if sum_obj[1] > 0.0:
                                weight_objs = map(lambda w: (w[0], w[1] / sum_obj[1]), weight_objs)
 
                            # Add more empty weight objects if too few
                            if len(weight_objs) != self.joints_per_vert:
                                weight_objs.extend([(0,0)] * (self.joints_per_vert - len(weight_objs)))
 
                            for w_obj in weight_objs:
                                index_data.append(w_obj[0])
                                weight_data.append(w_obj[1])
 
                            vert_it.next()
 
                        weight_stream = []
                        index_stream = []
 
                        # This list contains the old-index of each vertex in the AWD vertex stream
                        vert_indices = self.mesh_vert_indices[skin_path.fullPathName()]
                        for idx in vert_indices:
                            start_idx = idx*self.joints_per_vert
                            end_idx = start_idx + self.joints_per_vert
                            w_tuple = weight_data[start_idx:end_idx]
                            i_tuple = index_data[start_idx:end_idx]
                            weight_stream.extend(w_tuple)
                            index_stream.extend(i_tuple)
 
                        if len(md) == 1:
                            print('Setting streams!')
                            sub = md[0]
                            sub.add_stream(pyawd.geom.STR_JOINT_WEIGHTS, weight_stream)
                            sub.add_stream(pyawd.geom.STR_JOINT_INDICES, index_stream)
                        else:
                            print('skinning not implemented for meshes with <> 1 sub-mesh')
 
            dag_it.next()
Exemplo n.º 10
0
def bSaveVertexSkinValues(inputFile, ignoreSoftSelection):

    timeBefore = time.time()

    print 'saving Vertex skinWeights.. '

    if not ignoreSoftSelection:
        verts, softWeights = getSoftSelection()
    else:
        verts = cmds.ls(selection=True, flatten=True)

    vertIds = vertexToIdList(verts)
    selection = OpenMaya.MSelectionList()
    OpenMaya.MGlobal.getActiveSelectionList(selection)

    iterate = OpenMaya.MItSelectionList(selection)
    dagPath = OpenMaya.MDagPath()
    component = OpenMaya.MObject()
    iterate.getDagPath(dagPath, component)

    skinCluster = bFindSkinCluster(
        OpenMaya.MFnDagNode(dagPath).partialPathName())
    fnSkinCluster = OpenMayaAnim.MFnSkinCluster(skinCluster)

    if not skinCluster.hasFn(OpenMaya.MFn.kSkinClusterFilter):
        print 'no skinCluster found on selected vertices'
        return

    output = open(inputFile, 'w')
    output.write(str(OpenMaya.MItGeometry(bSkinPath).count()) + '\n')

    fnVtxComp = OpenMaya.MFnSingleIndexedComponent()
    vtxComponents = OpenMaya.MObject()
    vtxComponents = fnVtxComp.create(OpenMaya.MFn.kMeshVertComponent)

    WeightArray = OpenMaya.MFloatArray()
    meshIter = OpenMaya.MItMeshVertex(dagPath, component)
    #while not meshIter.isDone():
    for vertId in vertIds:
        fnVtxComp.addElement(vertId)
        #meshIter.next()

    vertexCount = meshIter.count()
    scriptUtil = OpenMaya.MScriptUtil()
    infCountPtr = scriptUtil.asUintPtr()
    fnSkinCluster.getWeights(bSkinPath, vtxComponents, WeightArray,
                             infCountPtr)
    infCount = OpenMaya.MScriptUtil.getUint(infCountPtr)

    weightCheckArray = []
    for i in range(infCount):
        weightCheckArray.append(False)

    for i in range(vertexCount):
        for k in range(infCount):
            if not weightCheckArray[k] and WeightArray[((i * infCount) + k)]:
                weightCheckArray[k] = True

    #joints..
    influentsArray = OpenMaya.MDagPathArray()
    fnSkinCluster.influenceObjects(influentsArray)
    for i in range(infCount):
        if (weightCheckArray[i]):
            output.write(OpenMaya.MFnDagNode(influentsArray[i]).name() + '\n')

    output.write('============\n')

    counter = 0
    weightArrayString = []
    for i in range(len(vertIds)):
        vertId = vertIds[i]
        softWeight = ''
        if not ignoreSoftSelection:
            softWeight = '%f:' % softWeights[i]

        #weightArrayString = '%d:%s' % (vertId, softWeight)
        """
        for k in range(infCount):
            if weightCheckArray[k] == True:
                weightArrayString += str(WeightArray[(counter * infCount) + k]) + ' '
        """
        weightsString = ' '.join([
            '0' if x == 0 else str(x)
            for n, x in enumerate(WeightArray[i * infCount:(i + 1) * infCount])
            if weightCheckArray[n]
        ])
        weightArrayString = "%d:%s%s" % (vertId, softWeight, weightsString)

        output.write(weightArrayString + '\n')
        counter += 1
        meshIter.next()

    output.close()

    print 'done, it took', (time.time() - timeBefore), ' seconds'
Exemplo n.º 11
0
def bSaveSkinValues(inputFile):

    timeBefore = time.time()

    output = open(inputFile, 'w')

    selection = OpenMaya.MSelectionList()
    OpenMaya.MGlobal.getActiveSelectionList(selection)

    iterate = OpenMaya.MItSelectionList(selection)

    while not iterate.isDone():
        node = OpenMaya.MDagPath()
        component = OpenMaya.MObject()
        iterate.getDagPath(node, component)
        if not node.hasFn(OpenMaya.MFn.kTransform):
            print OpenMaya.MFnDagNode(node).name(
            ) + ' is not a Transform node (need to select transform node of polyMesh)'
        else:
            objectName = OpenMaya.MFnDagNode(node).name()
            newTransform = OpenMaya.MFnTransform(node)
            for childIndex in range(newTransform.childCount()):
                childObject = newTransform.child(childIndex)
                if childObject.hasFn(OpenMaya.MFn.kMesh) or childObject.hasFn(
                        OpenMaya.MFn.kNurbsSurface) or childObject.hasFn(
                            OpenMaya.MFn.kCurve):
                    skinCluster = bFindSkinCluster(
                        OpenMaya.MFnDagNode(childObject).partialPathName())
                    if skinCluster is not False:
                        bSkinPath = OpenMaya.MDagPath()
                        fnSkinCluster = OpenMayaAnim.MFnSkinCluster(
                            skinCluster)
                        fnSkinCluster.getPathAtIndex(0, bSkinPath)
                        influenceArray = OpenMaya.MDagPathArray()
                        fnSkinCluster.influenceObjects(influenceArray)
                        influentsCount = influenceArray.length()
                        output.write(objectName + '\n')

                        for k in range(influentsCount):
                            jointTokens = str(
                                influenceArray[k].fullPathName()).split('|')
                            jointTokens = jointTokens[len(jointTokens) -
                                                      1].split(':')
                            output.write(jointTokens[len(jointTokens) - 1] +
                                         '\n')

                        output.write('============\n')

                        fnVtxComp = OpenMaya.MFnSingleIndexedComponent()
                        vtxComponents = OpenMaya.MObject()
                        vtxComponents = fnVtxComp.create(
                            OpenMaya.MFn.kMeshVertComponent)

                        vertexCount = OpenMaya.MFnMesh(bSkinPath).numVertices()
                        for i in range(vertexCount):
                            fnVtxComp.addElement(i)

                        WeightArray = OpenMaya.MFloatArray()
                        scriptUtil = OpenMaya.MScriptUtil()
                        infCountPtr = scriptUtil.asUintPtr()
                        fnSkinCluster.getWeights(bSkinPath, vtxComponents,
                                                 WeightArray, infCountPtr)
                        infCount = OpenMaya.MScriptUtil.getUint(infCountPtr)

                        for i in range(vertexCount):
                            #saveString = ' '.join(map(str,WeightArray[i*infCount : (i+1)*infCount]))
                            saveString = ' '.join([
                                '0' if x == 0 else str(x) for n, x in
                                enumerate(WeightArray[i * infCount:(i + 1) *
                                                      infCount])
                            ])

                            output.write(saveString + '\n')

                        output.write('\n')

        iterate.next()

    output.close()
    print 'done saving weights, it took ', (time.time() -
                                            timeBefore), ' seconds.'
Exemplo n.º 12
0
import maya.OpenMaya as OpenMaya
import maya.OpenMayaAnim as OpenMayaAnim
import maya.cmds as cmds
import maya.mel as mel

# poly mesh and skinCluster name
shapeName = 'pSphere1'
clusterName = 'skinCluster1'

# get the MFnSkinCluster for clusterName
selList = OpenMaya.MSelectionList()
selList.add(clusterName)
clusterNode = OpenMaya.MObject()
selList.getDependNode(0, clusterNode)
skinFn = OpenMayaAnim.MFnSkinCluster(clusterNode)

# get the MDagPath for all influence
infDags = OpenMaya.MDagPathArray()
skinFn.influenceObjects(infDags)

# create a dictionary whose key is the MPlug indice id and
# whose value is the influence list id
infIds = {}
infs = []
for x in xrange(infDags.length()):
	infPath = infDags[x].fullPathName()
	infId = int(skinFn.indexForInfluenceObject(infDags[x]))
	infIds[infId] = x
	infs.append(infPath)
    def redoIt(self):
        if len(self.points) < 3:
            return

        if self.aWeights.length():
            self.fnSkin.setWeights(self.dgPath, self.components,
                                   self.aInfluences, self.aWeights, False,
                                   self.aUndoWeights)
            return

        for i in range(len(self.points)):
            self.sel.add(self.points[i])
        self.sel.getDagPath(0, self.dgPath, self.components)

        skin = mc.ls(mc.listHistory(self.dgPath.partialPathName()),
                     type='skinCluster')
        if not skin:
            return
        else:
            self.skin = skin[0]

        self.sel.clear()
        self.sel.add(self.skin)
        oSkin = OpenMaya.MObject()
        self.sel.getDependNode(0, oSkin)
        self.fnSkin = OpenMayaAnim.MFnSkinCluster(oSkin)

        fComponents = OpenMaya.MFnSingleIndexedComponent(self.components)
        mc.setAttr(self.skin + '.envelope', 0.0)
        fnMesh = OpenMaya.MFnMesh(self.dgPath)
        fUV = self.sUtil.asFloat2Ptr()

        if self.UVSpace:
            dist = lambda a, b: math.sqrt((a[0] - b[0])**2 + (a[1] - b[1])**2)
        else:
            dist = lambda a, b: math.sqrt((a[0] - b[0])**2 + (a[1] - b[1])**2 +
                                          (a[2] - b[2])**2)

        maxDistance = 0
        for i in range(len(self.points)):
            for j in range(i + 1, len(self.points)):
                if self.UVSpace:
                    for k in range(2):
                        pntPos = mc.pointPosition(
                            self.points[(j * k) + (i * abs(1 - k))])
                        vPnt = OpenMaya.MFloatVector(pntPos[0], pntPos[1],
                                                     pntPos[2])
                        pPnt = OpenMaya.MPoint(vPnt)
                        fnMesh.getUVAtPoint(pPnt, fUV)
                        if k:
                            lPntB = [self.sUtil.getFloat2ArrayItem(fUV, 0, 0)]
                            lPntB.append(
                                self.sUtil.getFloat2ArrayItem(fUV, 0, 1))
                        else:
                            lPntA = [self.sUtil.getFloat2ArrayItem(fUV, 0, 0)]
                            lPntA.append(
                                self.sUtil.getFloat2ArrayItem(fUV, 0, 1))
                else:
                    lPntA = OpenMaya.MPoint()
                    fnMesh.getPoint(fComponents.element(i), lPntA)
                    lPntB = OpenMaya.MPoint()
                    fnMesh.getPoint(fComponents.element(j), lPntB)
                d = dist(lPntA, lPntB)
                if d > maxDistance:
                    maxDistance = d
                    maxPoint = self.points[j]
                    minPoint = self.points[i]
                    minDist = list(lPntA)

        self.sel.clear()
        self.sel.add(minPoint)
        self.sel.add(maxPoint)
        baseComponents = OpenMaya.MObject()
        self.sel.getDagPath(0, self.dgPath, baseComponents)

        ptrInfCount = self.sUtil.asUintPtr()
        aBaseWeights = OpenMaya.MDoubleArray()
        self.fnSkin.getWeights(self.dgPath, baseComponents, aBaseWeights,
                               ptrInfCount)
        iInfCount = self.sUtil.getUint(ptrInfCount)

        self.fnSkin.getWeights(self.dgPath, self.components, self.aWeights,
                               ptrInfCount)
        self.aUndoWeights.copy(self.aWeights)
        dgInfluences = OpenMaya.MDagPathArray()
        self.fnSkin.influenceObjects(dgInfluences)

        for i in range(iInfCount):
            self.aInfluences.append(i)

        for i in range(0, self.aWeights.length(), iInfCount):
            index = fComponents.element(i / iInfCount)
            pPnt = OpenMaya.MPoint()
            fnMesh.getPoint(index, pPnt)
            if self.UVSpace:
                fnMesh.getUVAtPoint(pPnt, fUV)
                lPnt = [self.sUtil.getFloat2ArrayItem(fUV, 0, 0)]
                lPnt.append(self.sUtil.getFloat2ArrayItem(fUV, 0, 1))
                dMin = dist(minDist, lPnt) / maxDistance
            else:
                dMin = dist(minDist, pPnt) / maxDistance

            if self.quadraticBlend:
                blend = lambda x, y: (x * (1.0 - dMin)**2) / (
                    maxDistance**2) + (y * (dMin)**2) / (maxDistance**2)

            else:
                blend = lambda x, y: (x * (1.0 - dMin)) + (y * dMin)

            for j in range(iInfCount):
                self.aWeights.set(
                    blend(aBaseWeights[j], aBaseWeights[iInfCount + j]), i + j)

            sumTotal = sum(self.aWeights[i:i + iInfCount])
            self.aWeights[i:i + iInfCount] = [
                x / sumTotal for x in self.aWeights[i:i + iInfCount]
            ]
        mc.setAttr(self.skin + '.envelope', 1.0)
        self.fnSkin.setWeights(self.dgPath, self.components, self.aInfluences,
                               self.aWeights, False, self.aUndoWeights)
Exemplo n.º 14
0
def saveWeights(mesh):
    filePath = cmds.file(q=1, l=1)[0].rsplit('/', 1)[0]
    fileName = filePath + '/%s_faceWeights.json' % mesh.name()

    skin = getSkin(mesh)

    if not skin:
        return 'no skin cluster found on %s' % node.name()

    # get the MFnskin for skin
    selList = OpenMaya.MSelectionList()
    selList.add(skin)
    skinNode = OpenMaya.MObject()
    selList.getDependNode(0, skinNode)
    skinFn = OpenMayaAnim.MFnSkinCluster(skinNode)

    # get the MDagPath for all influence
    infDags = OpenMaya.MDagPathArray()
    skinFn.influenceObjects(infDags)

    joints = [
        str(infDags[i].fullPathName().split('|')[-1])
        for i in range(infDags.length())
    ]
    print joints

    # get the MPlug for the weightList and weights attributes
    wlPlug = skinFn.findPlug('weightList')
    wPlug = skinFn.findPlug('weights')
    wlAttr = wlPlug.attribute()
    wAttr = wPlug.attribute()
    wInfIds = OpenMaya.MIntArray()

    weights = {}
    for vId in xrange(wlPlug.numElements()):
        vWeights = {}
        # tell the weights attribute which vertex id it represents
        wPlug.selectAncestorLogicalIndex(vId, wlAttr)

        # get the indice of all non-zero weights for this vert
        wPlug.getExistingArrayAttributeIndices(wInfIds)

        # create a copy of the current wPlug
        infPlug = OpenMaya.MPlug(wPlug)
        for infId in wInfIds:
            # tell the infPlug it represents the current influence id
            infPlug.selectAncestorLogicalIndex(infId, wAttr)

            # add this influence and its weight to this verts weights
            try:
                vWeights[str(infDags[infId].fullPathName().split('|')
                             [-1])] = infPlug.asDouble()
            except KeyError:
                # assumes a removed influence
                pass
        weights[vId] = vWeights

    weights['joints'] = joints

    with open(fileName, "w") as jsonFile:
        json.dump(weights, jsonFile, indent=2)

    return '%s saved succesfully' % fileName
Exemplo n.º 15
0
    def doIt(self, args):
        # get the skinCluster for the component
        # selected skinned geo
        selection = om.MSelectionList()
        om.MGlobal.getActiveSelectionList(selection)

        # get dag path for selection
        component = om.MObject()
        try:
            selection.getDagPath(0, self.dagPath, component)
            self.dagPath.extendToShape()
        except:
            return

        # get skincluster from shape
        itSkin = om.MItDependencyGraph(self.dagPath.node(),
                                       om.MFn.kSkinClusterFilter,
                                       om.MItDependencyGraph.kUpstream,
                                       om.MItDependencyGraph.kBreadthFirst,
                                       om.MItDependencyGraph.kPlugLevel)

        skcMObj = None
        while not itSkin.isDone():
            # current MObject in the iteration
            skcMObj = itSkin.currentItem()

            # here's our skinCluster node
            self.fnSkin = oma.MFnSkinCluster(skcMObj)

            # cast current MObj to MFnDependencyNode to get attribute value
            mFnDependSkinCluster = om.MFnDependencyNode(skcMObj)

            # get if maintain max influences is checked
            maintainMaxInfMPlug = mFnDependSkinCluster.findPlug(
                'maintainMaxInfluences')
            self.maintainMaxInfluences = maintainMaxInfMPlug.asBool()

            # get number of max influences to maintain
            maxInfMPlug = mFnDependSkinCluster.findPlug('maxInfluences')
            self.maxInfluences = maxInfMPlug.asInt()

            # done, break out
            break

        # check for skinCluster
        if not self.fnSkin:
            om.MGlobal.displayError(
                'Cannot find skinCluster node connected to component.')
            return

        # check if max influenc
        if self.maintainMaxInfluences == True and self.maxInfluences < 1:
            om.MGlobal.displayWarning(
                'Maintain max influences is ON and Max influences is set to 0. No weight will be set.'
            )
            return

        # # find tweak node
        # itMesh = om.MItDependencyGraph(skcMObj,
        # 	om.MFn.kMesh,
        # 	om.MItDependencyGraph.kUpstream,
        # 	om.MItDependencyGraph.kBreadthFirst,
        # 	om.MItDependencyGraph.kPlugLevel)

        # # iterate thru tweak connections looking for mesh
        # while not itMesh.isDone():
        # 	meshMObj = itMesh.currentItem()

        # 	# check if current item is an intermediate object
        # 	if om.MFnDagNode(meshMObj).isIntermediateObject() == True:
        # 		self.fnOrigMesh = om.MFnMesh(meshMObj)
        # 		break

        # 	itMesh.next()

        # # check for origMesh
        # if not self.fnOrigMesh:
        # 	om.MGlobal.displayError('Cannot find orig mesh of the deformation chain.')
        # 	return

        # parse flags
        argData = om.MArgDatabase(self.syntax(), args)
        # -index
        if argData.isFlagSet(kIndexFlag):
            self.index = argData.flagArgumentInt(kIndexFlag, 0)
        # -value
        if argData.isFlagSet(kValueFlag):
            self.pressure = argData.flagArgumentDouble(kValueFlag, 0)

        # do the actual work
        self.redoIt()
Exemplo n.º 16
0
def bLoadVertexSkinValues(inputFile):

    line = ''
    joints = []
    weights = []
    splittedStrings = []
    splittedWeights = []
    weightDoubles = OpenMaya.MDoubleArray()
    selectionList = OpenMaya.MSelectionList()
    vertexCount = 0

    OpenMaya.MGlobal.getActiveSelectionList(selectionList)
    node = OpenMaya.MDagPath()
    component = OpenMaya.MObject()
    selectionList.getDagPath( 0, node, component)

    if not node.hasFn(OpenMaya.MFn.kTransform):
        print 'select a skinned object'

    NewTransform = OpenMaya.MFnTransform(node)
    if not NewTransform.childCount() or not NewTransform.child(0).hasFn(OpenMaya.MFn.kMesh):
        print 'select a skinned object..'

    mesh = NewTransform.child(0)
    objectName = OpenMaya.MFnDagNode(mesh).name()
    skinCluster = bFindSkinCluster(objectName)
    if not skinCluster.hasFn(OpenMaya.MFn.kSkinClusterFilter):
        print 'select a skinned object'

    fnSkinCluster = OpenMayaAnim.MFnSkinCluster(skinCluster)
    input = open(inputFile, 'r')

    joints = []
    weightLines = []
    filePosition = 0
    while True:
        line = input.readline().strip()
        if not line:
            break

        if filePosition == 0:
            vertexCount = int(line)
            filePosition = 1
        elif filePosition == 1:
            if not line.startswith("========"):
                joints.append(line)
            else:
                filePosition = 2
        elif filePosition == 2:
            weightLines.append(line)

    if OpenMaya.MItGeometry(node).count() != vertexCount:
        print "vertex counts don't match, result might be bad"

    # joints..
    influenceArray = OpenMaya.MDagPathArray()
    influenceStringArray = []
    influenceMapArray = OpenMaya.MIntArray()
    jointsMapArray = OpenMaya.MIntArray()

    infCount = fnSkinCluster.influenceObjects(influenceArray)
    for i in range(infCount):
        influenceStringArray.append(OpenMaya.MFnDagNode(influenceArray[i]).name())      
        influenceMapArray.append(-1)
        for k in range(len(joints)):
            if influenceStringArray[i] == joints[k]:
                influenceMapArray[i] = k

    for i in range(len(joints)):
        jointsMapArray.append(-1)

    allInfluencesInScene = True
    influenceInScene = False
    for i in range(len(joints)):
        influenceInScene = False
        for k in range(len(influenceStringArray)):
            if influenceStringArray[k] == joints[i]:
                influenceInScene = True
                jointsMapArray[i] = k

        if not influenceInScene:
            allInfluencesInScene = False
            print joints[i], ' is missing in the skinCluster'

    if not allInfluencesInScene:
        print 'There are influences missing'
        return

    extraInfluencesCount = 0

    for i in range(len(influenceStringArray)):
        jointInInfluences = False
        for k in range(len(joints)):
            if joints[k] == influenceStringArray[i]:
                jointInInfluences = True
        if not jointInInfluences:
            jointsMapArray.append(i)
            extraInfluencesCount += 1

    # load points
    fnVtxComp = OpenMaya.MFnSingleIndexedComponent()
    vtxComponents = OpenMaya.MObject()
    vtxComponents = fnVtxComp.create(OpenMaya.MFn.kMeshVertComponent )

    for i in range(len(weightLines)):
        splittedStrings = weightLines[i].split(':')
        if len(splittedStrings) > 1:
            fnVtxComp.addElement(int(splittedStrings[0]))
            splittedWeights = splittedStrings[1].split(' ')
            for k in range(len(splittedWeights)):
                weightDoubles.append(float(splittedWeights[k]))

            weightDoubles += [0] * extraInfluencesCount

    # SET WEIGHTS
    fnSkinCluster.setWeights(bSkinPath, vtxComponents, jointsMapArray, weightDoubles, 0)

    # select the vertices
    pointSelectionList = OpenMaya.MSelectionList()
    pointSelectionList.add(OpenMaya.MDagPath(node), vtxComponents)
    OpenMaya.MGlobal.setActiveSelectionList(pointSelectionList)
Exemplo n.º 17
0
    def _fix(self, skinCluster):
        """
        :param str skinCluster:
        """
        obj = api.toMObject(skinCluster)
        skinFn = OpenMayaAnim.MFnSkinCluster(obj)

        # normalize
        normalize = "{0}.normalizeWeights".format(skinCluster)
        normalize = cmds.getAttr(normalize)

        # max influence data
        maxInfluences = "{0}.maxInfluences".format(skinCluster)
        maxInfluences = cmds.getAttr(maxInfluences)

        # get influences
        infIds, infPaths = skin.getInfluencesApi(skinFn)
        infIdsLocked = {
            i: cmds.getAttr("{0}.liw".format(infPaths[i]))
            for _, i in infIds.iteritems()
        }

        # get weights
        weights = skin.getWeightsApi(skinFn, infIds)

        for vId, vWeights in weights.iteritems():
            # variable
            nWeights = vWeights.copy()

            # sort weights
            ordered = sorted(vWeights.items(), key=lambda x: -x[1])

            keepIndices = [
                index for i, (index, weight) in enumerate(ordered)
                if i <= maxInfluences - 1
            ]
            removeIndices = [
                index for i, (index, weight) in enumerate(ordered)
                if i > maxInfluences - 1
            ]

            # remove weights
            for i in removeIndices:
                nWeights[i] = 0

            # normalize weights
            if normalize == 1:
                # get normalizable weights
                normalizeIndices = [
                    i for i in keepIndices if not infIdsLocked.get(i)
                ]

                # if no weights can be normalized, normalize all
                if not normalizeIndices:
                    normalizeIndices = keepIndices

                # get normalizing multiplier
                total = sum([vWeights.get(i) for i in normalizeIndices])
                multiplier = 1 / total

                # normalize indices
                for i in normalizeIndices:
                    nWeights[i] = vWeights.get(i) * multiplier

            # set weights
            for infId, infValue in nWeights.items():
                infAttr = "{0}.weightList[{1}].weights[{2}]".format(
                    skinCluster, vId, infId)
                cmds.setAttr(infAttr, infValue)
Exemplo n.º 18
0
def bSaveVertexSkinValues(inputFile):
    print 'saving Vertex skinWeights.. '

    selection = OpenMaya.MSelectionList()
    OpenMaya.MGlobal.getActiveSelectionList(selection)
    iterate = OpenMaya.MItSelectionList(selection)
    while not iterate.isDone():
        dagPath = OpenMaya.MDagPath()
        component = OpenMaya.MObject()
        iterate.getDagPath(dagPath, component)
        skinCluster = bFindSkinCluster(OpenMaya.MFnDagNode(dagPath).partialPathName())
        fnSkinCluster = OpenMayaAnim.MFnSkinCluster(skinCluster)
        iterate.next()

        if skinCluster.hasFn(OpenMaya.MFn.kSkinClusterFilter):
            output = open(inputFile, 'w')
            output.write(str(OpenMaya.MItGeometry(bSkinPath).count()) + '\n')

            fnVtxComp = OpenMaya.MFnSingleIndexedComponent()
            vtxComponents = OpenMaya.MObject()
            vtxComponents = fnVtxComp.create(OpenMaya.MFn.kMeshVertComponent)

            WeightArray = OpenMaya.MFloatArray()
            meshIter = OpenMaya.MItMeshVertex(dagPath, component)
            while not meshIter.isDone():
                fnVtxComp.addElement(meshIter.index())
                meshIter.next()

            vertexCount = meshIter.count()
            scriptUtil = OpenMaya.MScriptUtil()
            infCountPtr = scriptUtil.asUintPtr()     
            fnSkinCluster.getWeights(bSkinPath, vtxComponents, WeightArray, infCountPtr)
            infCount = OpenMaya.MScriptUtil.getUint(infCountPtr)

            weightCheckArray = []
            for i in range(infCount):
                weightCheckArray.append(False)

            for i in range(vertexCount):
                for k in range(infCount):
                    if not weightCheckArray[k] and WeightArray[((i * infCount) + k)]:
                        weightCheckArray[k] = True

            #joints.. 
            InfluentsArray = OpenMaya.MDagPathArray()
            fnSkinCluster.influenceObjects(InfluentsArray)
            for i in range(infCount):
                if weightCheckArray[i]:
                    output.write(OpenMaya.MFnDagNode(InfluentsArray[i]).name() + '\n')

            output.write('============\n')

            counter = 0
            weightArrayString = []
            meshIter = OpenMaya.MItMeshVertex(dagPath, component)
            while not meshIter.isDone():
                weightArrayString = str(meshIter.index()) + ':'

                for k in range(infCount):
                    if weightCheckArray[k] == True:
                        weightArrayString += str(WeightArray[(counter * infCount) + k]) + ' '

                output.write(weightArrayString + '\n')
                counter += 1
                meshIter.next()

            output.close()
            iterate.next()
Exemplo n.º 19
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!')
Exemplo n.º 20
0
def bSaveSkinValues(inputFile):

    output = open(inputFile, 'w')

    selection = OpenMaya.MSelectionList()
    OpenMaya.MGlobal.getActiveSelectionList(selection)

    iterate = OpenMaya.MItSelectionList(selection)

    while not iterate.isDone():
        node = OpenMaya.MDagPath()
        component = OpenMaya.MObject()
        iterate.getDagPath (node, component)
        if not node.hasFn(OpenMaya.MFn.kTransform):
            print OpenMaya.MFnDagNode(node).name() + ' is not a Transform node (need to select transform node of polyMesh)'
        else:
            objectName = OpenMaya.MFnDagNode(node).name()
            newTransform = OpenMaya.MFnTransform(node)
            for childIndex in range(newTransform.childCount()):
                childObject = newTransform.child(childIndex)
                if childObject.hasFn(OpenMaya.MFn.kMesh) or childObject.hasFn(OpenMaya.MFn.kNurbsSurface) or childObject.hasFn(OpenMaya.MFn.kCurve):
                    skinCluster = bFindSkinCluster(OpenMaya.MFnDagNode(childObject).partialPathName())
                    if skinCluster is not False:
                        bSkinPath = OpenMaya.MDagPath()
                        fnSkinCluster = OpenMayaAnim.MFnSkinCluster(skinCluster)
                        fnSkinCluster.getPathAtIndex(0,bSkinPath)
                        influenceArray = OpenMaya.MDagPathArray()
                        fnSkinCluster.influenceObjects(influenceArray)
                        influentsCount = influenceArray.length()
                        #output.write(bSkinPath.partialPathName() + '\n')
                        output.write(objectName + '\n')

                        for k in range(influentsCount):
                            jointTokens = str(influenceArray[k].fullPathName()).split('|')
                            jointTokens = jointTokens[len(jointTokens)-1].split(':')
                            output.write(jointTokens[len(jointTokens)-1] + '\n')

                        output.write('============\n')

                        vertexIter = OpenMaya.MItGeometry(bSkinPath)

                        saveString = ''
                        counterValue = 0
                        while not vertexIter.isDone():
                            counterValue = counterValue + 1
                            vertex = vertexIter.component()

                            scriptUtil = OpenMaya.MScriptUtil()
                            infCountPtr = scriptUtil.asUintPtr()     
                            vtxComponents = OpenMaya.MObject()     
                            weightArray = OpenMaya.MDoubleArray()  

                            fnSkinCluster.getWeights(bSkinPath, vertex, weightArray, infCountPtr)

                            saveString = ''

                            for j in range(OpenMaya.MScriptUtil.getUint(infCountPtr)):
                                saveString += str(weightArray[j])
                                saveString += ' '

                            output.write(saveString + '\n')

                            vertexIter.next()
                        output.write('\n')


        iterate.next()

    output.close()
    print "done saving weights"
Exemplo n.º 21
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
Exemplo n.º 22
0
def bSkinObject(objectName, joints, weights):

    if not cmds.objExists(objectName):
        print objectName, " doesn't exist - skipping. "
        return
    
    allInfluencesInScene = True
    jointsCheck = [] 
    for i in range(len(joints)):
        jointsCheck = joints[i]

    sceneJointTokens = []
    fileJointTokens = []

    it = OpenMaya.MItDependencyNodes ( OpenMaya.MFn.kJoint)
    # quick check:
    for jointIndex in range(len(joints)):
        jointHere = False
        it = OpenMaya.MItDependencyNodes ( OpenMaya.MFn.kJoint)
        while not it.isDone():                
            sceneJointTokens = str(OpenMaya.MFnDagNode(it.item()).fullPathName()).split('|')
            if str(joints[jointIndex]) == str(sceneJointTokens[len(sceneJointTokens) - 1]):
                jointHere = True

            it.next()

        if not jointHere:
            allInfluencesInScene = False
            print 'missing influence: ', joints[jointIndex]



    if not allInfluencesInScene:
        print objectName, " can't be skinned because of missing influences."
        return

    #maya.mel.eval("undoInfo -st 0")

    
    if type(bFindSkinCluster(objectName)) != type(True):
        maya.mel.eval("DetachSkin " + objectName)

    cmd = "select "
    for i in range(len(joints)):
        cmd += " " + joints[i]

    cmd += " " + objectName
    maya.mel.eval(cmd)

    maya.mel.eval("skinCluster -tsb -mi 10")
    maya.mel.eval("select `listRelatives -p " + objectName + "`")
    maya.mel.eval("refresh")
    #maya.mel.eval("undoInfo -st 1")

    skinCluster = bFindSkinCluster(objectName)
    fnSkinCluster = OpenMayaAnim.MFnSkinCluster(skinCluster)
    InfluentsArray = OpenMaya.MDagPathArray()
    fnSkinCluster.influenceObjects(InfluentsArray)

    bSkinPath = OpenMaya.MDagPath()
    fnSkinCluster.getPathAtIndex(fnSkinCluster.indexForOutputConnection(0),bSkinPath)

    weightStrings = []
    vertexIter = OpenMaya.MItGeometry (bSkinPath)

    weightDoubles = OpenMaya.MDoubleArray()


    singleIndexed = True
    vtxComponents = OpenMaya.MObject()
    fnVtxComp = OpenMaya.MFnSingleIndexedComponent()
    fnVtxCompDouble = OpenMaya.MFnDoubleIndexedComponent()

    
    if bSkinPath.node().apiType() == OpenMaya.MFn.kMesh:
        vtxComponents = fnVtxComp.create( OpenMaya.MFn.kMeshVertComponent )
    elif bSkinPath.node().apiType() == OpenMaya.MFn.kNurbsSurface:
        singleIndexed = False
        vtxComponents = fnVtxCompDouble.create( OpenMaya.MFn.kSurfaceCVComponent )
    elif bSkinPath.node().apiType() == OpenMaya.MFn.kNurbsCurve:
        vtxComponents = fnVtxComp.create( OpenMaya.MFn.kCurveCVComponent )
   
    #mapping joint-indices
    influenceIndices = OpenMaya.MIntArray()
    checkInfluences = []

    for k in range(InfluentsArray.length()):
        checkInfluences.append(0)
    for i in range(len(joints)):
        influenceIndices.append(-1)

    for i in range(len(joints)):
        fileJointTokens = joints[i].split('|')

        for k in range(InfluentsArray.length()):

            sceneJointTokens = str(OpenMaya.MFnDagNode(InfluentsArray[k]).fullPathName()).split('|')
            if fileJointTokens[len(fileJointTokens) - 1] == sceneJointTokens[len(sceneJointTokens) - 1]:  # changed from joints
                influenceIndices[i] = k
                checkInfluences[k] = 1        

    counterValue = 0
    if not singleIndexed:
        currentU = 0
        currentV = 0

        cvsU = OpenMaya.MFnNurbsSurface(bSkinPath.node()).numCVsInU()
        cvsV = OpenMaya.MFnNurbsSurface(bSkinPath.node()).numCVsInV()
        formU = OpenMaya.MFnNurbsSurface(bSkinPath.node()).formInU()
        formV = OpenMaya.MFnNurbsSurface(bSkinPath.node()).formInV()
        if formU == 3:
            cvsU -= 3
        if formV == 3:
            cvsV -= 3
    
    vertexIter = OpenMaya.MItGeometry(bSkinPath)
    while not vertexIter.isDone():
        weightStrings = []
        if singleIndexed:
            fnVtxComp.addElement(counterValue)
        else:
            fnVtxCompDouble.addElement(currentU, currentV)
            currentV += 1
            if currentV >= cvsV:
                currentV = 0
                currentU += 1

        weightStrings = weights[counterValue].split(' ')
        for i in range(len(weightStrings)):
            weightDoubles.append(float(weightStrings[i]))
        counterValue += 1
        vertexIter.next()

    #SET WEIGHTS 
    print "setting weights for  ", objectName
    fnSkinCluster.setWeights(bSkinPath, vtxComponents, influenceIndices,weightDoubles, 0)
    #Maya.mel.eval("skinPercent -normalize true " + fnSkinCluster.name() + " " + objectName)

    influenceIndices.clear()
    weightDoubles.clear()
Exemplo n.º 23
0
 def asMFnSkinCluster(self):
     assert (self.asMObject().hasFn(OpenMaya.MFn.kSkinClusterFilter)), "Object has no functions 'kSkinCluster'"
     scFn = OpenMayaAnim.MFnSkinCluster()
     scFn.setObject(self.asMObject())
     return scFn
Exemplo n.º 24
0
def readFile(filepath):
    files = path_wrangler(filepath)
    files.get_files()

    md = open(files.data['uexp'], 'rb')
    ua = open(files.data['uasset'], 'rb')

    meshName = files.data['meshName']
    submesh_name = files.data['submesh_name']

    arm = False
    weightData = {}
    Weight_array = []
    vertexArray = []
    NA = []
    normal_array = []

    faces = []

    U0 = om2.MFloatArray()
    V0 = om2.MFloatArray()
    U1 = om2.MFloatArray()
    V1 = om2.MFloatArray()
    U2 = om2.MFloatArray()
    V2 = om2.MFloatArray()
    U3 = om2.MFloatArray()
    V3 = om2.MFloatArray()
    U4 = om2.MFloatArray()
    V4 = om2.MFloatArray()
    U5 = om2.MFloatArray()
    V5 = om2.MFloatArray()

    t1 = time.time()
    names = readUasset(ua)

    pattern0 = re.compile(b'\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00........')
    for x in xrange(20000):
        s1 = struct.unpack("18s", md.read(18))[0]
        if pattern0.match(s1):
            c0 = struct.unpack("<L", md.read(4))[0]
            c1 = struct.unpack("<L", md.read(4))[0]
            c2 = struct.unpack("<L", md.read(4))[0]
            c3 = struct.unpack("<L", md.read(4))[0]
            c4 = struct.unpack("<L", md.read(4))[0]
            if (c0 and c1 and c2 and c3 and c4 > 1000000000):
                break
            else:
                md.seek(-20, 1)
        md.seek(-17, 1)

    materialCount = struct.unpack("<L", md.read(4))[0]
    materials = {}
    for m in xrange(materialCount):
        materials[m] = {}
        materials[m]['val0'] = struct.unpack("<l", md.read(4))[0]
        stringIndex = struct.unpack("<L", md.read(4))[0]
        unk0 = struct.unpack("<L", md.read(4))[0]
        unk1 = struct.unpack("<L", md.read(4))[0]
        unk2 = struct.unpack("<L", md.read(4))[0]
        unk3 = struct.unpack("<f", md.read(4))[0]
        unk4 = struct.unpack("<f", md.read(4))[0]
        unk5 = struct.unpack("<L", md.read(4))[0]
        unk6 = struct.unpack("<L", md.read(4))[0]

        materials[m]['name'] = names[stringIndex]

    boneCount = struct.unpack("<L", md.read(4))[0]
    joint_data = {}
    bt = np.empty([1, boneCount], dtype='U32')
    for i in xrange(boneCount):
        string_index = struct.unpack("<L", md.read(4))[0]
        jName = names[string_index]
        unk = struct.unpack("<L", md.read(4))[0]
        parent = struct.unpack("<l", md.read(4))[0]

        joint_data[i] = {"name": jName, "parent": parent}
        bt[0, i] = jName

    boneCount2 = struct.unpack("<L", md.read(4))[0]
    bone_list = []
    boneArray = []
    for k in xrange(boneCount2):
        m1 = struct.unpack("<10f", md.read(40))
        boneName = joint_data[k]["name"]
        BNparent = joint_data[k]["parent"]
        boneArray.append(boneName)

        BNps = om.MVector(-m1[5], -m1[6], m1[4])
        BNrt = om.MQuaternion(m1[1], m1[2], -m1[0], -m1[3])
        BNsc = om.MVector(-m1[8], -m1[9], -m1[7])

        if BNparent == -1:
            cmds.select(clear=True)
        else:
            pm.select(bone_list[BNparent])
        newBone = pm.joint(p=(0, 0, 0), name=boneName, radius=0.1)
        newBone.setTranslation(BNps)
        newBone.setOrientation(BNrt)
        newBone.setScale(BNsc)

        bone_list.append(newBone)
    arm = True

    boneCount3 = struct.unpack("<L", md.read(4))[0]
    md.seek(boneCount3 * 12, 1)

    vertexGroups = {}
    unk0 = struct.unpack("<L", md.read(4))[0]
    unk1 = struct.unpack("B", md.read(1))[0]
    unk2 = struct.unpack("B", md.read(1))[0]
    groupCount = struct.unpack("<L", md.read(4))[0]
    for m in xrange(groupCount):
        z1 = struct.unpack("<H", md.read(2))[0]
        ID = struct.unpack("<H", md.read(2))[0]

        md.seek(24, 1)
        vertexGroups[ID] = {'range': 0, 'bones': []}

        # pragma region bone palette
        start = struct.unpack("<L", md.read(4))[0]
        count = struct.unpack("<L", md.read(4))[0]
        bt = np.empty([1, count], dtype='U32')
        for bn in xrange(count):
            bid = struct.unpack("<H", md.read(2))[0]
            vertexGroups[ID]['bones'].append(bid)
            bt[0, bn] = joint_data[bid]["name"]
        # pragma endregion bone palette

        size = struct.unpack("<L", md.read(4))[0]
        stop = start + size
        vertexGroups[ID]['range'] = range(start, stop)
        vertexGroups[ID]["start"] = start
        vertexGroups[ID]["stop"] = stop
        vertexGroups[ID]["size"] = size
        vertexGroups[ID]["names"] = bt

        md.seek(34, 1)
        FFx4 = readHexString(md, 4)
        flag = struct.unpack("<L", md.read(4))[0]
        if flag:  # extra data for this group
            count = struct.unpack("<L", md.read(4))[0]
            md.seek(count * 16, 1)
        else:
            null = struct.unpack("<L", md.read(4))[0]

    unk = struct.unpack("B", md.read(1))[0]
    checkHere = md.tell()
    stride = struct.unpack("<L", md.read(4))[0]
    fCount = struct.unpack("<L", md.read(4))[0]

    faceByteCount = fCount * stride
    fi = np.fromfile(md, dtype='B', count=faceByteCount)
    if stride == 4:
        fi_0 = fi.view(dtype='<L').reshape(fCount // 3, 3)
    elif stride == 2:
        fi_0 = fi.view(dtype='<H').reshape(fCount // 3, 3)
    fi_1 = fi_0.ravel()
    faces = tuple(fi_1)

    pCounts = [3] * (len(faces) // 3)

    gh = pCounts[0]

    unkCount = struct.unpack("<L", md.read(4))[0]
    md.seek(unkCount * 2, 1)

    unk = struct.unpack("<L", md.read(4))[0]
    vertexCount = struct.unpack("<L", md.read(4))[0]
    boneCount = struct.unpack("<L", md.read(4))[0]
    md.seek(boneCount * 2, 1)

    null0 = struct.unpack("<L", md.read(4))[0]
    null1 = struct.unpack("<L", md.read(4))[0]

    uv_count = struct.unpack("<L", md.read(4))[0]
    unk0 = struct.unpack("<H", md.read(2))[0]
    uv_count2 = struct.unpack("<L", md.read(4))[0]

    null2 = struct.unpack("<L", md.read(4))[0]

    unk1 = struct.unpack("<f", md.read(4))[0]
    unk2 = struct.unpack("<f", md.read(4))[0]
    unk3 = struct.unpack("<f", md.read(4))[0]

    null3 = struct.unpack("<L", md.read(4))[0]
    null4 = struct.unpack("<L", md.read(4))[0]
    null5 = struct.unpack("<L", md.read(4))[0]

    vStride = struct.unpack("<L", md.read(4))[0]
    vCount = struct.unpack("<L", md.read(4))[0]

    byteCount = vCount * vStride
    vi = np.fromfile(md, dtype='B', count=byteCount).reshape((vCount, vStride))
    pos = vi[:, 8:20].ravel().view(dtype='<f').reshape((vCount, 3))
    pos[:, [0, 2]] = pos[:, [2, 0]]
    pos[:, [0, 1]] = pos[:, [1, 0]]
    pos[:, [2]] *= -1
    positions = pos.tolist()
    VA = om2.MFloatPointArray(positions)

    if uv_count > 0:
        uvData_ = vi[:, 20:24].ravel().view(dtype='<f2').reshape((vCount, 2))
        uvData_[:, 1:2] *= -1
        uvData_[:, 1:2] += 1
        uvData = tuple(map(tuple, uvData_))
        u = zip(*uvData)[0]
        v = zip(*uvData)[1]
        U0.copy(u)
        V0.copy(v)
    if uv_count > 1:
        uvData_ = vi[:, 24:28].ravel().view(dtype='<f2').reshape((vCount, 2))
        uvData_[:, 1:2] *= -1
        uvData_[:, 1:2] += 1
        uvData = tuple(map(tuple, uvData_))
        u = zip(*uvData)[0]
        v = zip(*uvData)[1]
        U1.copy(u)
        V1.copy(v)
    if uv_count > 2:
        uvData_ = vi[:, 28:32].ravel().view(dtype='<f2').reshape((vCount, 2))
        uvData_[:, 1:2] *= -1
        uvData_[:, 1:2] += 1
        uvData = tuple(map(tuple, uvData_))
        u = zip(*uvData)[0]
        v = zip(*uvData)[1]
        U2.copy(u)
        V2.copy(v)
    if uv_count > 3:
        uvData_ = vi[:, 32:36].ravel().view(dtype='<f2').reshape((vCount, 2))
        uvData_[:, 1:2] *= -1
        uvData_[:, 1:2] += 1
        uvData = tuple(map(tuple, uvData_))
        u = zip(*uvData)[0]
        v = zip(*uvData)[1]
        U3.copy(u)
        V3.copy(v)
    if uv_count > 4:
        uvData_ = vi[:, 36:40].ravel().view(dtype='<f2').reshape((vCount, 2))
        uvData_[:, 1:2] *= -1
        uvData_[:, 1:2] += 1
        uvData = tuple(map(tuple, uvData_))
        u = zip(*uvData)[0]
        v = zip(*uvData)[1]
        U4.copy(u)
        V4.copy(v)

    mesh = om2.MFnMesh()
    ShapeMesh = cmds.group(em=True)
    parentOwner = get_mobject(ShapeMesh)
    meshMObj = mesh.create(VA,
                           pCounts,
                           faces,
                           uValues=U0,
                           vValues=V0,
                           parent=parentOwner)

    cmds.sets(ShapeMesh, e=True, forceElement='initialShadingGroup')

    cmds.polyUVSet(rename=True,
                   newUVSet='map_0',
                   uvSet=mesh.currentUVSetName(-1))
    mesh.setUVs(U0, V0, 'map_0')
    mesh.assignUVs(pCounts, faces, 'map_0')

    cmds.rename(meshName)

    s1 = cmds.ls(sl=1)
    s2 = s1[0]
    shapeName = s2.encode('ascii', 'ignore')

    if uv_count > 1:
        mesh.createUVSet('map_1')
        mesh.setUVs(U1, V1, 'map_1')
        mesh.assignUVs(pCounts, faces, 'map_1')
    if uv_count > 2:
        mesh.createUVSet('map_2')
        mesh.setUVs(U2, V2, 'map_2')
        mesh.assignUVs(pCounts, faces, 'map_2')
    if uv_count > 3:
        mesh.createUVSet('map_3')
        mesh.setUVs(U3, V3, 'map_3')
        mesh.assignUVs(pCounts, faces, 'map_3')
    if uv_count > 4:
        mesh.createUVSet('map_4')
        mesh.setUVs(U4, V4, 'map_4')
        mesh.assignUVs(pCounts, faces, 'map_4')

    unkS = struct.unpack("<H", md.read(2))[0]
    extraBoneWeights = struct.unpack("<L", md.read(4))[0]
    wCount = struct.unpack("<L", md.read(4))[0]
    stride = struct.unpack("<L", md.read(4))[0]
    wCount2 = struct.unpack("<L", md.read(4))[0]

    subStride = int(stride / 2)

    clusterName = shapeName + '_' + 'skinCluster'
    pm.skinCluster(boneArray[:], shapeName, sm=1, mi=8, omi=1, n=clusterName)

    skin = mm.eval('findRelatedSkinCluster "' + s2 + '"')

    sel = om.MSelectionList()
    sel.add(shapeName)
    meshMObject = om.MObject()
    sel.getDependNode(0, meshMObject)

    sel2 = om.MSelectionList()
    sel2.add(skin)
    skinMObject = om.MObject()
    sel2.getDependNode(0, skinMObject)

    FnSkin = oma.MFnSkinCluster(skinMObject)
    dag_path, skinMObject = get_skin_dag_path_and_mobject(FnSkin)
    weights = om.MDoubleArray()
    influence_paths = om.MDagPathArray()
    influence_count = FnSkin.influenceObjects(influence_paths)
    components_per_influence = weights.length() / influence_count

    # influences
    unused_influences = list()
    influences = [
        influence_paths[inf_count].partialPathName()
        for inf_count in xrange(influence_paths.length())
    ]

    wSize = vCount * influence_count
    weights = om.MDoubleArray(wSize, 0.0)

    w_byteCount = wCount * stride
    wi = np.fromfile(md, dtype='B', count=w_byteCount).reshape(
        (wCount, stride))
    wi_b = wi[:, :subStride].ravel().view().reshape((wCount, subStride))
    wi_w = wi[:, subStride:stride].ravel().view().reshape(
        (wCount, subStride)).astype(np.float64)
    wi_w /= 255.0

    def do_stuff(n):
        fg = influences.index(L[n])
        idx = fg + (j * influence_count)
        weights[idx] = W[n]

    for h in xrange(len(vertexGroups)):
        crnt_grp = vertexGroups[h]
        g_names = crnt_grp["names"]
        g_range = crnt_grp["range"]
        for j in g_range:
            Wt = np.trim_zeros(wi_w[j], 'b')
            W = tuple(Wt)
            a = Wt.shape[0]
            ids = wi_b[j, :a]
            L = tuple(g_names[0, ids])

            map(do_stuff, range(len(L)))
    influence_array = om.MIntArray(influence_count)
    m_util.createIntArrayFromList(range(influence_count), influence_array)
    FnSkin.setWeights(dag_path, skinMObject, influence_array, weights, False)

    createMaterials(files, vertexGroups, materials, shapeName)

    pm.select(shapeName)
    cmds.viewFit()

    elapsed = time.time() - t1
    return elapsed

    md.close()
    ua.close()
Exemplo n.º 25
0
def SaveTFXBoneBinaryFile(filepath, selected_mesh_shape_name, meshShapedagPath,
                          rootPositions):
    #---------------------------------------------------------------------------
    # Build a face/triangle index list to convert face index into triangle index
    #---------------------------------------------------------------------------
    faceIter = OpenMaya.MItMeshPolygon(meshShapedagPath)
    triangleCount = 0
    faceTriaIndexList = []
    index = 0

    util = OpenMaya.MScriptUtil()
    util.createFromInt(0)

    while not faceIter.isDone():
        faceTriaIndexList.append(triangleCount)

        if faceIter.hasValidTriangulation():
            numTrianglesPtr = util.asIntPtr()
            faceIter.numTriangles(numTrianglesPtr)
            numTriangles = util.getInt(numTrianglesPtr)
            triangleCount += numTriangles

        faceIter.next()

    #print "TressFX: Triangle count:%d\n" % triangleCount

    #----------------------
    # Find the closest face
    #----------------------
    meshFn = OpenMaya.MFnMesh(meshShapedagPath)
    meshIntersector = OpenMaya.MMeshIntersector()
    meshIntersector.create(meshShapedagPath.node())

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

    vertexTriangleList = []

    triangleIdForStrandsList = []
    baryCoordList = []
    uvCoordList = []
    pointOnMeshList = []

    progressBar = ProgressBar('Collecting bone data', len(rootPositions))

    for i in range(len(rootPositions)):
        rootPoint = rootPositions[i]

        # Find the closest point info
        meshPt = OpenMaya.MPointOnMesh()
        meshIntersector.getClosestPoint(rootPoint, meshPt)
        pt = meshPt.getPoint()

        pointOnMesh = OpenMaya.MPoint()
        pointOnMesh.x = pt.x
        pointOnMesh.y = pt.y
        pointOnMesh.z = pt.z
        pointOnMeshList.append(pointOnMesh)

        # Find face index
        faceId = meshPt.faceIndex()

        # Find triangle index
        triangleId = faceTriaIndexList[faceId] + meshPt.triangleIndex()

        dummy = OpenMaya.MScriptUtil()
        dummyIntPtr = dummy.asIntPtr()
        triangleId_local = meshPt.triangleIndex(
        )  # This values is either 0 or 1. It is not a global triangle index. triangleId is the global triangle index.
        pointArray = OpenMaya.MPointArray()
        vertIdList = OpenMaya.MIntArray()
        faceIter.setIndex(faceId, dummyIntPtr)
        faceIter.getTriangle(triangleId_local, pointArray, vertIdList,
                             OpenMaya.MSpace.kWorld)

        vertexTriangleList.append(
            (vertIdList[0], vertIdList[1], vertIdList[2]))
        triangleIdForStrandsList.append(triangleId)

        # Find three vertex indices for the triangle. Following two lines should give us three correct vertex indices for the triangle. I haven't really verified though.
        #vertexIndex = [triangleVertexIndices[triangleId*3], triangleVertexIndices[triangleId*3+1], triangleVertexIndices[triangleId*3+2]]
        vertexIndex = [vertIdList[0], vertIdList[1], vertIdList[2]]

        # Find barycentric coordinates
        uvw = OpenMaya.MPoint()

        # Somehow, below code gives me negative barycentric coordinates sometimes.
        # uPtr = OpenMaya.MScriptUtil().asFloatPtr()
        # vPtr = OpenMaya.MScriptUtil().asFloatPtr()
        # meshPt.getBarycentricCoords(uPtr,vPtr)
        # uvw.x = OpenMaya.MScriptUtil(uPtr).asFloat()
        # uvw.y = OpenMaya.MScriptUtil(vPtr).asFloat()
        # uvw.z = 1.0 - uvw.x - uvw.y

        # Instead getting barycentric coords from getBarycentricCoords, we compute it by the following function.
        uvw_a = ComputeBarycentricCoordinates(pointArray[0], pointArray[1],
                                              pointArray[2], pointOnMesh)

        uvw.x = uvw_a[0]
        uvw.y = uvw_a[1]
        uvw.z = uvw_a[2]

        # barycentric coordinates should be non-zero
        uvw.x = max(uvw.x, 0)
        uvw.y = max(uvw.y, 0)
        uvw.z = max(uvw.z, 0)

        # normalize barycentric coordinates so that their sum is equal to 1
        sum = uvw.x + uvw.y + uvw.z
        uvw.x /= sum
        uvw.y /= sum
        uvw.z /= sum

        baryCoordList.append(uvw)

        # Find UV coordinates - We don't really use UV coords for tfxbone file.
        # util = OpenMaya.MScriptUtil()
        # util.createFromList([0.0, 0.0], 2)
        # uv_ptr = util.asFloat2Ptr()
        # meshFn.getUVAtPoint(rootPoint, uv_ptr)
        # u = OpenMaya.MScriptUtil.getFloat2ArrayItem(uv_ptr, 0, 0)
        # v = OpenMaya.MScriptUtil.getFloat2ArrayItem(uv_ptr, 0, 1)
        # uv_coord = OpenMaya.MPoint()
        # uv_coord.x = u
        # uv_coord.y = v
        # uv_coord.z = 0
        # uvCoordList.append(uv_coord)

        # update progress gui
        progressBar.Increment()

    progressBar.Kill()

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

    #print skinClusterName

    #---------------------------------------------------------------------------------------------------
    # TODO: Try the following method.
    # skins = filter(lambda skin: mesh.getShape() in skin.getOutputGeometry(), ls(type='skinCluster'))

    # if len(skins) > 0 :
    # skin = skins[0]
    # skinJoints = skin.influenceObjects();
    # root = skinJoints[0]

    # while root.getParent() :
    # root = root.getParent()

    # skin.getWeights(mesh.verts[index])

    # select(root, hierarchy=True, replace=True)
    # joints = ls(selection=True, transforms=True, type='joint')
    #---------------------------------------------------------------------------------------------------

    # 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

    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
        geoIter.next()

    #------------------------
    # Save the tfxbone file.
    #------------------------
    progressBar = ProgressBar(
        'Saving a tfxbone file',
        len(influenceObjectsNames) + len(triangleIdForStrandsList))
    f = open(filepath, "wb")
    # Number of Bones
    f.write(ctypes.c_int(len(influenceObjectsNames)))

    # Write all bone (joint) names
    for i in range(len(influenceObjectsNames)):
        # Bone Joint Index
        f.write(ctypes.c_int(i))
        # Size of the string, add 1 to leave room for the nullterminate.
        f.write(ctypes.c_int(len(influenceObjectsNames[i]) + 1))
        # Print the characters of the string 1 by 1.
        for j in range(len(influenceObjectsNames[i])):
            f.write(ctypes.c_byte(ord(influenceObjectsNames[i][j])))
        # Add a zero to null terminate the string.
        f.write(ctypes.c_byte(0))
        progressBar.Increment()

    # Number of Strands
    f.write(ctypes.c_int(len(triangleIdForStrandsList)))

    for i in range(len(triangleIdForStrandsList)):
        triangleId = triangleIdForStrandsList[i]

        # three vertex indices from one triangle - Following two lines should work equally but I haven't verified it yet.
        #vertexIndices = [triangleVertexIndices[triangleId*3], triangleVertexIndices[triangleId*3+1], triangleVertexIndices[triangleId*3+2]]
        vertexIndices = vertexTriangleList[i]

        baryCoord = baryCoordList[i]
        weightJointIndexPairs = GetSortedWeightsFromTriangleVertices(
            TRESSFX_MAX_INFLUENTIAL_BONE_COUNT, vertexIndices, jointIndexArray,
            weightArray, baryCoord)

        # Index, the rest should be self explanatory.
        f.write(ctypes.c_int(i))
        f.write(ctypes.c_int(weightJointIndexPairs[0].joint_index))
        f.write(ctypes.c_float(weightJointIndexPairs[0].weight))
        f.write(ctypes.c_int(weightJointIndexPairs[1].joint_index))
        f.write(ctypes.c_float(weightJointIndexPairs[1].weight))
        f.write(ctypes.c_int(weightJointIndexPairs[2].joint_index))
        f.write(ctypes.c_float(weightJointIndexPairs[2].weight))
        f.write(ctypes.c_int(weightJointIndexPairs[3].joint_index))
        f.write(ctypes.c_float(weightJointIndexPairs[3].weight))
        progressBar.Increment()

    f.close()
    progressBar.Kill()
    return
Exemplo n.º 26
0
def getSkinWeights(skin):  # MAYA API
	influenceDict = {}

	# get the MFnSkinCluster for clusterName
	selList = OpenMaya.MSelectionList()
	selList.add(skin)
	clusterNode = OpenMaya.MObject()
	selList.getDependNode(0, clusterNode)
	skinFn = OpenMayaAnim.MFnSkinCluster(clusterNode)

	# get the MDagPath for all influence
	infDags = OpenMaya.MDagPathArray()
	skinFn.influenceObjects(infDags)

	# create a dictionary whose key is the MPlug indice id and
	# whose value is the influence list id
	infIds = {}
	infs = []
	for x in xrange(infDags.length()):
		infPath = infDags[x].fullPathName()
		infId = int(skinFn.indexForInfluenceObject(infDags[x]))
		infIds[infId] = x
		infs.append(infPath)
		influenceDict[infId] = infPath.split('|')[-1]

	# get the MPlug for the weightList and weights attributes
	wlPlug = skinFn.findPlug('weightList')
	wPlug = skinFn.findPlug('weights')
	wlAttr = wlPlug.attribute()
	wAttr = wPlug.attribute()
	wInfIds = OpenMaya.MIntArray()

	# the weights are stored in dictionary, the key is the vertId,
	# the value is another dictionary whose key is the influence id and
	# value is the weight for that influence
	weights = {}
	for vId in xrange(wlPlug.numElements()):
		vWeights = {}
		# tell the weights attribute which vertex id it represents
		wPlug.selectAncestorLogicalIndex(vId, wlAttr)

		# get the indice of all non-zero weights for this vert
		wPlug.getExistingArrayAttributeIndices(wInfIds)

		# create a copy of the current wPlug
		infPlug = OpenMaya.MPlug(wPlug)
		for infId in wInfIds:
			# tell the infPlug it represents the current influence id
			infPlug.selectAncestorLogicalIndex(infId, wAttr)

			# add this influence and its weight to this verts weights
			try:
				# vWeights[infIds[infId]] = infPlug.asDouble()
				vWeights[influenceDict[infId]] = {infIds[infId]: infPlug.asDouble()}

			except KeyError:
				# assumes a removed influence
				pass

		weights[vId] = vWeights

	return weights
Exemplo n.º 27
0
def pinocchioWeightsImport(mesh, skin, skelList, weightFile=None,
                           undoable=False):
    #Ensure that all influences in the skelList are influences for the skin
    allInfluences = influenceObjects(skin)
    pinocInfluences = [joint for joint, parent in skelList]
    for joint in pinocInfluences:
        if not nodeIn(joint, allInfluences):
            cmds.skinCluster(skin, edit=1, addInfluence=joint)

    if weightFile is None:
        weightFile = browseForFile(m=0, actionName='Import')
    vertBoneWeights = readPinocchioWeights(weightFile)
    numVertices = len(vertBoneWeights)
    numBones = len(vertBoneWeights[0])
    numJoints = len(skelList)
    numWeights = numVertices * numJoints
    if DEBUG:
        print "numVertices:", numVertices
        print "numBones:", numBones
    assert numBones == numJoints - 1, \
           "numBones (%d) != numJoints (%d) - 1" % (numBones, numJoints)

    # Pinocchio sets weights per-bone... maya weights per joint.
    # Need to decide whether to assign the bone weight to the 'start' joint
    #   of the bone, or the 'end' joint
    boneIndexToJointIndex = [0] * numBones
    vertJointWeights = [[0] * numJoints for i in xrange(numVertices)]

    assignBoneToEndJoint = False
    if assignBoneToEndJoint:
        for jointIndex in xrange(1, numJoints):
            boneIndexToJointIndex[jointIndex - 1] = jointIndex
    else:
        for jointIndex in xrange(1, numJoints):
            parentIndex = skelList[jointIndex][1]
            boneIndexToJointIndex[jointIndex - 1] = parentIndex
    
    for vertIndex, boneWeights in enumerate(vertBoneWeights):
        assert abs(sum(boneWeights) - 1) < 0.1, \
               "Output for vert %d not normalized - total was: %.03f" % \
               (vertIndex, sum(boneWeights))
        for boneIndex, boneValue in enumerate(boneWeights):
            # multiple bones can correspond to a single joint -
            # make sure to add the various bones values together!
            jointIndex = boneIndexToJointIndex[boneIndex] 
            vertJointWeights[vertIndex][jointIndex] += boneValue

    if DEBUG:
        print "vertJointWeights:"
        for i, jointWeights in enumerate(vertJointWeights):
            if i < 20:
                print jointWeights
            else:
                print "..."
                break
    
    if not undoable:
        # If we're using the non-undoable api method, there's a lot of setup
        # we have to do first; want to do this before zeroing weights,
        # in case there's an error 
        apiWeights = api.MDoubleArray(numWeights, 0)
        for vertIndex, jointWeights in enumerate(vertJointWeights):
            for jointIndex, jointValue in enumerate(jointWeights):
                apiWeights.set(jointValue, vertIndex * numJoints + jointIndex)
        apiJointIndices = api.MIntArray(numJoints, 0)
        if DEBUG:
            for jointIndex, (joint, parentIndex) in enumerate(skelList):
                print jointIndex, (joint, parentIndex)
        influences = influenceObjects(skin)
        for apiIndex, joint in enumerate(influences):
            influenceIndex = getNodeIndex(joint, pinocInfluences)
            if influenceIndex is None:
                raise InfluenceNotFoundError("%r not found in influences for skin %r: %r" %
                                             (joint, skin, pinocInfluences))
            apiJointIndices.set(apiIndex, influenceIndex)
        if DEBUG:
            print "apiJointIndices:",
            pyJointIndices = []
            for i in xrange(apiJointIndices.length()):
                pyJointIndices.append(apiJointIndices[i])
            print pyJointIndices
        apiComponents = api.MFnSingleIndexedComponent().create(api.MFn.kMeshVertComponent)
        apiVertices = api.MIntArray(numVertices, 0)
        for i in xrange(numVertices):
            apiVertices.set(i, i)
        api.MFnSingleIndexedComponent(apiComponents).addElements(apiVertices) 
        mfnSkin = apiAnim.MFnSkinCluster(toMObject(skin))
        meshDag = toMDagPath(mesh)
        # Save the weights, so that if there's an error later, we
        # can still restore the weights
        savedWeights = api.MDoubleArray(numWeights, 0)
        numInfluencesPtr = api.MScriptUtil()
        numInfluencesPtr.createFromInt(0) 
        mfnSkin.getWeights(meshDag, apiComponents, savedWeights,
                           numInfluencesPtr.asUintPtr())
        
    # Zero all weights (so if there's influences not among those we're
    # importing, they will have zero influence)
    cmds.skinPercent(skin, mesh, pruneWeights=100, normalize=False)

    if not undoable:
        # Use the api methods to set skin weights - MUCH faster than using
        # mel skinPercent, but api doesn't have built-in undo support, so
        # flush the undo queue
        zeroedWeights = api.MDoubleArray()
        undoState = cmds.undoInfo(q=1, state=1)
        cmds.undoInfo(state=False)
        try:
            try:
                mfnSkin.setWeights(meshDag,
                                   apiComponents,
                                   apiJointIndices,
                                   apiWeights,
                                   False,
                                   zeroedWeights)
                print "successfully set weights!"
            except Exception:
                # There was a problem, restore the saved weights!
                influenceIndices = api.MIntArray(len(influences), 0)
                for i in xrange(len(influences)):
                    influenceIndices.set(i,i)
                mfnSkin.setWeights(meshDag,
                                   apiComponents,
                                   influenceIndices,
                                   savedWeights,
                                   False,
                                   zeroedWeights)
                api.MGlobal.displayError("Encountered error setting new weights - original weights restored")
                raise
        finally:
            cmds.flushUndo()
            cmds.undoInfo(state=undoState)
    else:
        # Use mel skinPercent - much slower, but undoable
        cmds.progressWindow(title="Setting new weights...", isInterruptable=True,
                            max=numVertices)
        try:
            lastUpdateTime = cmds.timerX()
            updateInterval = .5
            for vertIndex, vertJoints in enumerate(vertJointWeights):
                jointValues = {}
                if cmds.progressWindow( query=True, isCancelled=True ) :
                    break
                #print "weighting vert:", vertIndex
                for jointIndex, jointValue in enumerate(vertJoints):
                    if jointValue > 0:
                        jointValues[pinocInfluences[jointIndex]] = jointValue
        
                if cmds.timerX(startTime=lastUpdateTime) > updateInterval:
                    cmds.progressWindow(edit=True,
                                        progress=vertIndex,
                                        status="Setting Vert: (%i of %i)" % (vertIndex, numVertices))
                    lastUpdateTime = cmds.timerX()
    
                cmds.skinPercent(skin, mesh + ".vtx[%d]" % vertIndex, normalize=False,
                                 transformValue=jointValues.items())
        finally:
            cmds.progressWindow(endProgress=True)    
Exemplo n.º 28
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)
Exemplo n.º 29
0
def bLoadVertexSkinValues(inputFile, ignoreJointLocks):
    timeBefore = time.time()

    line = ''
    fileJoints = []
    weights = []
    splittedStrings = []
    splittedWeights = []
    selectionList = OpenMaya.MSelectionList()
    vertexCount = 0

    OpenMaya.MGlobal.getActiveSelectionList(selectionList)
    node = OpenMaya.MDagPath()
    component = OpenMaya.MObject()
    selectionList.getDagPath(0, node, component)

    if not node.hasFn(OpenMaya.MFn.kTransform):
        print 'select a skinned object'

    NewTransform = OpenMaya.MFnTransform(node)
    if not NewTransform.childCount() or not NewTransform.child(0).hasFn(
            OpenMaya.MFn.kMesh):
        print 'select a skinned object..'

    mesh = NewTransform.child(0)
    objectName = OpenMaya.MFnDagNode(mesh).name()
    skinCluster = bFindSkinCluster(objectName)
    if not skinCluster.hasFn(OpenMaya.MFn.kSkinClusterFilter):
        print 'select a skinned object'

    fnSkinCluster = OpenMayaAnim.MFnSkinCluster(skinCluster)
    input = open(inputFile, 'r')

    fileJoints = []
    weightLines = []
    filePosition = 0

    # getting the weightLines
    #
    fileWeightFloats = []
    fnVtxComp = OpenMaya.MFnSingleIndexedComponent()
    vtxComponents = OpenMaya.MObject()
    vtxComponents = fnVtxComp.create(OpenMaya.MFn.kMeshVertComponent)

    bindVertCount = 0
    didCheckSoftSelection = False
    while True:
        line = input.readline().strip()
        if not line:
            break

        if filePosition == 0:
            vertexCount = int(line)
            if OpenMaya.MItGeometry(node).count() != vertexCount:
                print "vertex counts don't match!"
                return
            filePosition = 1

        elif filePosition == 1:
            if not line.startswith("========"):
                fileJoints.append(line)
            else:
                filePosition = 2

        elif filePosition == 2:
            splittedStrings = line.split(':')

            # do we have softselection?
            if not didCheckSoftSelection:
                if len(splittedStrings) == 3:
                    weightsIndex = 2
                    doSoftSelection = True
                    softWeights = [1.0] * bindVertCount
                else:
                    weightsIndex = 1
                    doSoftSelection = False
                didCheckSoftSelection = True

            # vertId
            vertId = int(splittedStrings[0])
            fnVtxComp.addElement(vertId)

            #softselection
            if doSoftSelection:
                softWeights.append(float(splittedStrings[1]))

            # weights
            splittedWeights = splittedStrings[weightsIndex].split(' ')
            fileWeightFloats.append(map(float, splittedWeights))

            #for k in range(len(fileJoints)):
            #    fileWeightFloats[bindVertCount].append(float(splittedWeights[k]))

            bindVertCount += 1

    #print 'fileWeightFloats: ', fileWeightFloats

    # getting mayaJoints
    #
    influenceArray = OpenMaya.MDagPathArray()
    mayaJoints = []

    infCount = fnSkinCluster.influenceObjects(influenceArray)
    for i in range(infCount):
        mayaJoints.append(
            OpenMaya.MFnDagNode(influenceArray[i]).name().split('|')[-1])

    # getting old weights
    #
    oldWeightDoubles = OpenMaya.MDoubleArray()
    scriptUtil = OpenMaya.MScriptUtil()
    infCountPtr = scriptUtil.asUintPtr()
    fnSkinCluster.getWeights(bSkinPath, vtxComponents, oldWeightDoubles,
                             infCountPtr)

    # making allJoints
    #
    allJoints = list(fileJoints)
    for mayaJoint in mayaJoints:
        if mayaJoint not in fileJoints:
            allJoints.append(mayaJoint)

    # mapping joints and making sure we have all joints in the skinCluster
    #
    allInfluencesInScene = True
    missingInfluencesList = []
    for i in range(len(fileJoints)):
        influenceInScene = False
        for k in range(len(mayaJoints)):
            if mayaJoints[k] == fileJoints[i]:
                influenceInScene = True

        if not influenceInScene:
            allInfluencesInScene = False
            missingInfluencesList.append(fileJoints[i])

    if not allInfluencesInScene:
        print 'There are influences missing:', missingInfluencesList
        return

    # getting allExistInMaya
    #
    allExistInMaya = [-1] * len(allJoints)
    for i in range(len(allJoints)):
        for k in range(len(mayaJoints)):
            if allJoints[i] == mayaJoints[k]:
                allExistInMaya[i] = k
                break

    #print 'allExistInMaya: ', allExistInMaya

    # getting joint locks
    #
    allLocks = [False] * len(allJoints)
    if not ignoreJointLocks:
        for i in range(len(allJoints)):
            allLocks[i] = cmds.getAttr('%s.liw' % allJoints[i])

    weightDoubles = OpenMaya.MDoubleArray(0)

    # copy weights from fileWeightFloats and oldWeightDoubles into weightDoubles (include joint locks) and softWeights lists
    #
    print 'bindVertCount: ', bindVertCount
    for i in range(bindVertCount):
        for k in range(len(allJoints)):

            # fileJoints:
            #
            if k < len(fileJoints):
                if not allLocks[k]:
                    weightDoubles.append(
                        fileWeightFloats[i][k]
                    )  #weightDoubles[k + len(allJoints) * i] = fileWeightFloats[i][k]
                else:
                    if allExistInMaya[k]:
                        weightDoubles.append(
                            oldWeightDoubles[allExistInMaya[k] +
                                             len(mayaJoints) * i])
                    else:
                        weightDoubles.append(0)

            # mayaJoints
            #
            else:
                if not allLocks[k]:
                    weightDoubles.append(0)
                else:
                    if allExistInMaya[k]:
                        weightDoubles.append(
                            oldWeightDoubles[allExistInMaya[k] +
                                             len(mayaJoints) * i])
                    else:
                        weightDoubles.append(0)

    # normalize
    #
    for i in range(bindVertCount):
        sumA = 0
        sumB = 0
        for inf in range(len(allJoints)):
            if not allLocks[inf]:
                sumA += weightDoubles[inf + i * len(allJoints)]
            else:
                sumB += weightDoubles[inf + i * len(allJoints)]

        if sumA > 0.0001:
            sumADenom = 1 / sumA
            for inf in range(len(allJoints)):
                if not allLocks[inf]:
                    weightDoubles[inf +
                                  i * len(allJoints)] *= sumADenom * (1 - sumB)

    # soft selection
    #
    if doSoftSelection:
        for i in range(bindVertCount):
            for inf in range(len(allExistInMaya)):
                index = inf + i * len(allExistInMaya)
                oldWeights = oldWeightDoubles[allExistInMaya[inf] +
                                              len(mayaJoints) * i]

                weightDoubles[index] = weightDoubles[index] * softWeights[
                    i] + oldWeights * (1.0 - softWeights[i])

    #SET WEIGHTS
    #
    allJointsIndices = OpenMaya.MIntArray(len(allExistInMaya))
    for i in range(len(allExistInMaya)):
        allJointsIndices[i] = allExistInMaya[i]

    #print 'mayaJoints: ', mayaJoints
    #print 'allJointsIndices: ', allJointsIndices
    #print 'allJoints: ', allJoints
    #print 'weightDoubles before: ', weightDoubles

    print 'setting weights...'
    fnSkinCluster.setWeights(bSkinPath, vtxComponents, allJointsIndices,
                             weightDoubles, 0)

    # select the vertices
    #
    pointSelectionList = OpenMaya.MSelectionList()
    pointSelectionList.add(OpenMaya.MDagPath(node), vtxComponents)
    OpenMaya.MGlobal.setActiveSelectionList(pointSelectionList)

    print 'done, it took', (time.time() - timeBefore), ' seconds'
Exemplo n.º 30
0
def deLinearSkinWeights(vertices, method):
	"""
	Loop over all of the provided vertices. Loop over all of the vertices and 
	see if these vertices are deformed by a skin cluster. If this is the case, 
	the weights will be de-linearized by the function provided. This function
	is found in the tweening module using :func:`getTweeningMethod`.
	
	:param list vertices: List of vertices
	:param str method: De-linearization method
	"""
	func = getTweeningMethod(method)
	if not func:
		raise ValueError("Tweening method is not supported.")

	data = {}
	objects = list(set([vtx.split(".")[0] for vtx in vertices]))
	
	with utils.UndoChunkContext():
		for obj in objects:
			# get skin cluster
			sk = utils.getSkinCluster(obj)
			if not sk:
				continue
			
			# get indices
			indices = [
				getIndexFromString(vtx) 
				for vtx in vertices 
				if vtx.startswith(obj)
			]
			
			# get api objects
			meshObj = utils.asMObject(obj)
			meshDag = utils.asMDagPath(meshObj)
			meshDag.extendToShape()
			
			skObj = utils.asMObject(sk)
			skMfn = OpenMayaAnim.MFnSkinCluster(skObj)
			
			# get weights
			components = utils.asComponent(indices)
			weightsAll, num = utils.getSkinWeights(
				meshDag, 
				skMfn, 
				components
			)
			
			# split weights
			weightChunks = splitByInfluences(weightsAll, num)

			for i, weights in enumerate(weightChunks):
				# calculate per vertex weights
				weights = utils.normalizeWeights(weights)
				weights = [func(w) for w in weights]
				weights = utils.normalizeWeights(weights)
				
				# set weights
				for j, w in enumerate(weights):
					cmds.setAttr(
						"{0}.weightList[{1}].weights[{2}]".format(
							sk, 
							indices[i],
							j
						), 
						w
					)