Ejemplo n.º 1
0
def getSkinWeights(meshDagPath, skinNode):
    """
    get skin weight per vertex for each joint
    :param meshDagPath: MDagPath, MDagPath of mesh shape node
    :param skinNode:MObject, MObject of skinCluster node
    :return: dict, mesh skin weight for each joint Per vertex.
             dict={0:{joint1:0.1, ..., jointX: 0.0}, ..., x:{joint1:0.03, ..., jointX:0.2}}
    """
    meshNode = meshDagPath.node()

    skinFn = oma2.MFnSkinCluster(skinNode)

    meshVertIterFn = om2.MItMeshVertex(meshNode)
    indices = range(meshVertIterFn.count())

    data = {}
    for i in indices:

        singleIDComponent = om2.MFnSingleIndexedComponent()
        vertexComponent = singleIDComponent.create(om2.MFn.kMeshVertComponent)
        singleIDComponent.addElement(indices[i])

        rawWeightDataPerVertex = skinFn.getWeights(meshDagPath,
                                                   vertexComponent)

        influecesObjs = skinFn.influenceObjects()

        data[i] = {}

        for j in xrange(influecesObjs.__len__()):
            data[i][
                influecesObjs[j].fullPathName()] = rawWeightDataPerVertex[0][j]

    return data
    def redoIt(self):
        # get the skin cluster MObject by going up the history

        fnSkinCluster = omAnim.MFnSkinCluster(self.skinClusterMObject)

        oldVertexWeight, numInfluences = fnSkinCluster.getWeights(
            self.dagPath, self.component)
        neighborVertexWeights, numInfluences = fnSkinCluster.getWeights(
            self.dagPath, self.neighborComponents)

        influenceIndices = om.MIntArray()
        newWeights = om.MDoubleArray()

        for i in xrange(numInfluences):
            # set the vertex weight to the average of its neighbor parts
            influenceIndices.append(i)
            newWeights.append(0.0)
            for j in xrange(i, len(neighborVertexWeights), numInfluences):
                # add to a rolling average. This will be normalized by default.
                # NOTE bmorgan: This formula comes from tf_smoothSkinWeight
                newWeights[i] += (
                    ((neighborVertexWeights[j] / self.numVertexNeighbors) *
                     self.strength) +
                    ((oldVertexWeight[i] / self.numVertexNeighbors) *
                     (1 - self.strength)))

        fnSkinCluster.setWeights(self.dagPath, self.component,
                                 influenceIndices, newWeights)

        self.undoQueue.append((self.skinClusterMObject, oldVertexWeight,
                               self.dagPath, influenceIndices, self.component))
Ejemplo n.º 3
0
def set_weights(skin, data, prune=False):
    """Set an skin cluster with weight data.

    Args:
        skin: Skin cluster node or mobject
        data: Weight data specifically in the format `get_weights` returns
        prune: Remove unused influences from the skin cluster

    Returns:
        None
    """
    influences = get_skin_influences(skin)
    influences_remapped = {v: k for k, v in influences.items()}
    mfn_skin = oma2.MFnSkinCluster(skin)
    for vert, weights in data:
        weight_list_index_attr = '{skincluster}.weightList[{vertId}]'.format(
            skincluster=mfn_skin.name(), vertId=vert)
        for influence, weight_value in weights:
            influence_logical_index = influences_remapped[influence]
            weights_attr = '.weights[{influenceId}]'.format(
                influenceId=influence_logical_index)
            cmds.setAttr(weight_list_index_attr + weights_attr, weight_value)
    if prune:
        skin_name = om2.MFnDependencyNode(skin).name()
        skin_geo = om2.MFnDependencyNode(
            oma2.MFnGeometryFilter(skin).getOutputGeometry()[0]).name()
        cmds.skinPercent(skin_name, skin_geo, nrm=False, prw=0)
Ejemplo n.º 4
0
def export_xml_weights(file_name, skins):
    """Save out skin weights to an XML file.

    Args:
        file_name: Name for output file
        skins: Skin clusters to gather skin weights from

    Returns:
        str: File path to output weights file
    """
    weights_dir = get_weights_directory()

    if not os.path.exists(weights_dir):
        os.makedirs(weights_dir)

    output_file_name = '{}.xml'.format(file_name)

    skin_names = [oma2.MFnSkinCluster(v).name() for k, v in skins.items()]
    output_path = cmds.deformerWeights(output_file_name,
                                       p=weights_dir,
                                       ex=True,
                                       vc=True,
                                       deformer=skin_names)

    return output_path
Ejemplo n.º 5
0
def get_skin_influences(skin):
    """Get a skin clusters influence list.

    Args:
        skin: Skin cluster name or mobject

    Returns:
        dict: A map where keys are the logical index and values are the names of the influences
    """
    influences = dict()

    sel = om2.MSelectionList()
    sel.add(skin)
    skin_mobject = sel.getDependNode(0)
    mfn_skin = oma2.MFnSkinCluster(skin_mobject)

    mfn_influences = mfn_skin.influenceObjects()

    for num in range(len(mfn_influences)):
        influence_idx = om2.MFnDependencyNode(
            mfn_influences[num].node()).uuid().asString()
        logical_index = mfn_skin.indexForInfluenceObject(mfn_influences[num])
        influences[int(logical_index)] = influence_idx

    return influences
    def redoIt(self):
        fnSkinCluster = omAnim.MFnSkinCluster(self.skinClusterMObject)

        # get the weights for our single vertex plus its neighbors
        oldVertexWeight, numInfluences = fnSkinCluster.getWeights(self.shapeDag, self.component)
        neighborVertexWeights, numInfluences = fnSkinCluster.getWeights(self.shapeDag, self.neighborComponents)
        neighborVertexWeightLength = self.numVertexNeighbors * numInfluences

        influenceIndices = om.MIntArray()
        newWeights = om.MDoubleArray()

        # set the vertex weight to the average of its neighbor parts
        for i in xrange(numInfluences):
            # taking advantage of this loop to create our influence indices array
            influenceIndices.append(i)
            # weights start at 0 so that we can add weight values to it
            newWeights.append(0.0)
            for j in xrange(i, neighborVertexWeightLength, numInfluences):
                # add to a rolling average. This will be normalized by default.
                # NOTE bmorgan: This formula comes from tf_smoothSkinWeight
                newWeights[i] += (((neighborVertexWeights[j] / self.numVertexNeighbors) * self.strength) +
                                  ((oldVertexWeight[i] / self.numVertexNeighbors) * (1 - self.strength)))

        # set the skin cluster weight for just that single component
        fnSkinCluster.setWeights(self.shapeDag, self.component, influenceIndices, newWeights)

        # add the previous weight value to our undo queue
        self.undoQueue.append((self.skinClusterMObject, oldVertexWeight, self.shapeDag, influenceIndices, self.component))
Ejemplo n.º 7
0
def setWeigths(skinNode, geo, inf, weigth):
    #获得一个组件列表
    cmp_list = [universal.intoComponents(i) for i in universal.translateToName(geo)]
    #检查组件列表的数量
    if len(cmp_list)<1:
        raise EOFError('geo没有任何对象')
    #建立一个组件选择列表
    sel_list = om.MSelectionList()
    [sel_list.add(i) for i in cmp_list]
    if int(sel_list.length())>1:
        raise EOFError('%s 不在一个mesh或者其他对象上'%geo)
        return 1
    path,comp = sel_list.getComponent(0)
    sel_list.add(skinNode)
    skinNode = sel_list.getDependNode(1)


    fn_skin = oma.MFnSkinCluster(skinNode)

    m_inf = om.MIntArray(inf)
    m_weigth = om.MDoubleArray(weigth)
    #撤销的权重
    unWeights = fn_skin.getWeights(path,comp,m_inf)

    doIt = functools.partial(fn_skin.setWeights,path,comp,m_inf,m_weigth)
    undoIt = functools.partial(fn_skin.setWeights,path,comp,m_inf,unWeights)
    return cmcore.addCommand(doIt, undoIt)
Ejemplo n.º 8
0
    def getSkinInfluences(self, scList):
        """

        :param scList:
        :return:
        """
        if scList:
            outputDict = dict()

            for sc in scList:
                mFnSkin = om2anim.MFnSkinCluster(sc)
                infObj = mFnSkin.influenceObjects()
                scName = mFnSkin.name()
                scNameNoNS = scName.split(':')[-1]
                jntList = list()

                for jnt in infObj:
                    jntName = om2.MDagPath(jnt).fullPathName().split(':')[-1]
                    if not jntName in jntList:
                        jntList.append(jntName)
                    else:
                        continue
                outputDict.update({scNameNoNS: jntList})

            return outputDict
Ejemplo n.º 9
0
    def vtxLoad_api(self):
        selList = om.MGlobal.getActiveSelectionList()
        if selList.isEmpty():
            om.MGlobal.displayError('Select Nothing')
            return
        MDagPath = selList.getDagPath(0)  # 存储所选物体的路径
        MObject = selList.getDependNode(0)  # 存储所选物体的组件的列表

        _selType = MDagPath.apiType()
        _selShapeType = MDagPath.extendToShape().apiType()
        if _selType != 110:
            om.MGlobal.displayError('Please Select Object')
            return
        if _selShapeType != 296:
            self.vtxLoad_Oapi()
            return

        skCluster = mel.eval('findRelatedSkinCluster("%s")' % MDagPath.partialPathName())
        if not skCluster:
            return
        selList.add(skCluster)
        skinObj = selList.getDependNode(1)
        skinNode = omAni.MFnSkinCluster(skinObj)
        infs = skinNode.influenceObjects()
        infNameList = [infs[i].partialPathName() for i in range(len(infs))]  # 骨骼列表

        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.MItMeshVertex(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!')
Ejemplo n.º 10
0
def set_skin_cluster_weights(mesh, skin_cluster, weights):
    """Set all weights on skin cluster via MFnSkinCluster.

    Weights should be in same form as returned by
    get_skin_cluster_weights.

    TODO options for selective influences.
    TODO options for selective components.

    """
    sl = OpenMaya.MSelectionList()

    # get mesh dag path
    sl.add(mesh)
    mesh_dag = sl.getDagPath(0)

    # get skin
    sl.add(skin_cluster)
    m_skin = sl.getDependNode(1)

    # restructure weights to match form expected by MFnSkinCluster
    n_weights = numpy.array(weights)
    flat_weights = n_weights.transpose().flatten().tolist()
    weights = OpenMaya.MDoubleArray(flat_weights)

    if True:
        # construct component object for all verts
        # TODO perform on specific components?!?
        mesh_fn = OpenMaya.MFnMesh(mesh_dag)
        point_count = mesh_fn.numVertices

        component = OpenMaya.MFnSingleIndexedComponent()
        component.create(OpenMaya.MFn.kMeshVertComponent)
        component.addElements([i for i in range(point_count)])

        components = component.object()

    else:
        # or simply pass in an empty MObject to set all weights
        # note sometimes this doesn't work?!
        components = OpenMaya.MObject()

    # set weights
    m_skin = OpenMayaAnim.MFnSkinCluster(m_skin)

    influences = [
        m_skin.indexForInfluenceObject(i) for i in m_skin.influenceObjects()
    ]

    # influences must be passed in as a MIntArray
    # python list will throw an unhelpful error
    # Error: TypeError: file ...py line 116: an integer is required #

    influences = OpenMaya.MIntArray(influences)

    m_skin.setWeights(mesh_dag, components, influences, weights)

    return True
Ejemplo n.º 11
0
 def __init__(self, cluster):
     """
     :param cluster: The skinCluster MObject
     :type cluster: om2.MObject
     """
     self.cluster = cluster
     self.mfn = om2Anim.MFnSkinCluster(cluster)
     self.shapeNode, self.component = geometryComponentsFromSet(
         self.mfn.deformerSet)
Ejemplo n.º 12
0
def getMFnSkinCluster(name):
    sel = OpenMaya.MSelectionList()
    try:
        sel.add(str(name))
    except RuntimeError as e:
        return e

    m_object = sel.getDependNode(0)
    return OpenMayaAnim.MFnSkinCluster(m_object)
    def undoIt(self):
        if self.undoQueue:
            fnSkinCluster = omAnim.MFnSkinCluster(self.undoQueue[-1][0])
            oldWeight = self.undoQueue[-1][1]
            shapeDag = self.undoQueue[-1][2]
            influenceIndices = self.undoQueue[-1][3]
            component = self.undoQueue[-1][4]
            # when undoing, we're also only setting the weight on that single vertex
            fnSkinCluster.setWeights(shapeDag, component, influenceIndices, oldWeight)

            # after we've set weights, remove that data from the undo queue
            self.undoQueue.pop(-1)
    def undoIt(self):
        if self.undoQueue:
            fnSkinCluster = omAnim.MFnSkinCluster(self.undoQueue[-1][0])
            oldWeights = self.undoQueue[-1][1]
            meshDagPath = self.undoQueue[-1][2]
            influenceIndices = self.undoQueue[-1][3]
            component = self.undoQueue[-1][4]
            # when undoing, we have to set weights on every component
            fnSkinCluster.setWeights(meshDagPath, component, influenceIndices,
                                     oldWeights)

            self.undoQueue.pop(-1)
Ejemplo n.º 15
0
 def getSkinFn(self):
     sel = om.MGlobal.getActiveSelectionList()
     meshDag = sel.getDagPath(0)
     meshDag.extendToShape()
     selList = om.MSelectionList()
     selList.add(meshDag)
     shapeObj = selList.getDependNode(0)
     dagIter = om.MItDependencyGraph(shapeObj, om.MItDependencyGraph.kDownstream, om.MItDependencyGraph.kPlugLevel)
     while not dagIter.isDone():
         currentItem = dagIter.currentNode()
         if currentItem.hasFn(om.MFn.kSkinClusterFilter):
             self.skinFn = oma.MFnSkinCluster(currentItem)
         dagIter.next()
Ejemplo n.º 16
0
 def om_get_skin_cluster(self, dagPath=None):
     if not dagPath:
         return None
     skinCluster = cmds.ls(cmds.listHistory(dagPath.fullPathName()), type='skinCluster')
     if not skinCluster:
         return None, None
     clusterName =skinCluster[0]
     sellist = om2.MGlobal.getSelectionListByName(clusterName)
     
     skinNode = sellist.getDependNode(0)
     skinFn = oma2.MFnSkinCluster( skinNode )
     #print('get skin cluster :', clusterName, skinFn)
     return skinFn, clusterName
Ejemplo n.º 17
0
def get_skin_data(mesh):
    """
    :param mesh: Pymel Transform Node
    :return: influences, skin_weights
    """

    skin_cluster = mesh.listHistory(type='skinCluster')[0]
    sel_list = OpenMaya.MSelectionList()
    sel_list.add(str(skin_cluster))
    cluster_node = sel_list.getDependNode(0)
    skin_fn = OpenMayaAnim.MFnSkinCluster(cluster_node)
    inf_dags = skin_fn.influenceObjects()
    """checking the update"""
Ejemplo n.º 18
0
 def get_skin_cluster(self, mesh_fn):
     '''
     get a list of all the skin clusters in the file, iterate and see if the shapes connected match our selection
     '''
     self.in_plug = mesh_fn.findPlug('inMesh', False)
     connections = self.in_plug.connectedTo(True, False)
     for c in connections:
         obj = c.node()
         try:
             skin_cluster_fn = oma.MFnSkinCluster(obj)
             return skin_cluster_fn
         except:
             sys.stderr.write("No skin cluster found! ")
             return None
Ejemplo n.º 19
0
    def vtxSave_api(self):
        selList = om.MGlobal.getActiveSelectionList()
        if selList.isEmpty():
            om.MGlobal.displayError('Select Nothing')
            return
        MDagPath = selList.getDagPath(0)  # 存储所选物体的路径
        MObject = selList.getDependNode(0)  # 存储所选物体的组件的列表
        slMIt = om.MItSelectionList(selList)
        MItDagPath, MItcomponent = slMIt.getComponent()

        _selType = MDagPath.apiType()
        _selShapeType = MDagPath.extendToShape().apiType()
        if not _selType in set([110, 296, 267, 294, 279, ]):
            return
        elif _selShapeType == 296:
            suf = 'vtx'
        elif _selShapeType == 267 or _selShapeType == 294 or _selShapeType == 279:
            self.vtxSave_Oapi()
            return

        skCluster = mel.eval('findRelatedSkinCluster("%s")' % MDagPath.partialPathName())
        if not skCluster:
            return
        selList.add(skCluster)
        skinObj = selList.getDependNode(1)
        skinNode = omAni.MFnSkinCluster(skinObj)
        infs = skinNode.influenceObjects()
        infNameList = [infs[i].partialPathName() for i in range(len(infs))]  # 骨骼列表

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

            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!')
Ejemplo n.º 20
0
def simplify_weights(path,
                     target=None,
                     fast=True,
                     deformer=None,
                     start=None,
                     end=None,
                     steps=1):
    """
    Simplify weighting on the mesh so that each vertice may only have a single influence.

    :param path: The path to the mesh to simplify the weights on
    :param target: The target mesh to compare weights against. Defaults to the current mesh.
    :param fast: Use the fast mode (less accurate) or not (iterates frame range but better results)
    :param deformer: The skin cluster to simplify weights for
    :param start: The start frame to use for the non-fast path.
    :param end: The end frame to use for the non-fast path.
    :param steps: The intervals between frames to use for the non fast path
    """
    sel = om.MSelectionList()
    sel.add(get_mesh(path))
    dag = sel.getDagPath(sel.length() - 1)
    mesh = om.MFnMesh(dag)

    if target:
        sel.add(get_mesh(target))
        target = sel.getDagPath(sel.length() - 1)
        target_mesh = om.MFnMesh(target)
    else:
        target = dag
        target_mesh = mesh

    if not deformer:
        deformer = get_skincluster(mesh.fullPathName())

    sel.add(deformer)
    skin_node = sel.getDependNode(sel.length() - 1)
    skin_cluster = oma.MFnSkinCluster(skin_node)

    if fast:
        __simplify_weights_fast(mesh, skin_cluster)
    else:
        __simplify_weights(mesh,
                           target_mesh,
                           skin_cluster,
                           start=start,
                           end=end,
                           steps=steps)
Ejemplo n.º 21
0
    def __init__(self,skinNode, geo):
        #获得一个组件列表
        cmp_list = [universal.intoComponents(i) for i in universal.translateToName(geo)]
        #检查组件列表的数量
        if len(cmp_list)<1:
            raise EOFError('geo没有任何对象')
        #建立一个组件选择列表
        sel_list = om.MSelectionList()
        [sel_list.add(i) for i in cmp_list]
        if int(sel_list.length())>1:
            raise EOFError('%s 不在一个mesh或者其他对象上'%geo)
            return 1
        self.path,self.comp = sel_list.getComponent(0)
        sel_list.add(skinNode)
        skinNode = sel_list.getDependNode(1)

        self.fn_skin = oma.MFnSkinCluster(skinNode)
Ejemplo n.º 22
0
def get_weights(skin, prune=False, use_influence_names=False):
    """Given a skin cluster node, gather all the weight data in sequential vertex order.

    Args:
        skin: Skin cluster name or mobject
        prune: Remove skin weight data that is zero
        use_influence_names: Use node names instead of node UUIDs

    Returns:
        list: Skin weights nested by vertex order, then influence order
    """
    data = list()

    mfn_skin = oma2.MFnSkinCluster(skin)
    influences = get_skin_influences(skin)

    if use_influence_names:
        influences = {
            k: cmds.ls(v, long=True)[0]
            for k, v in influences.items()
        }

    weight_list_attr = mfn_skin.findPlug('weightList', False)
    vertices = weight_list_attr.getExistingArrayAttributeIndices()

    weight_list_attr.evaluateNumElements()

    for vert in vertices:
        weights = list()
        weight_list_index_attr = weight_list_attr.elementByLogicalIndex(vert)
        weights_attr = weight_list_index_attr.child(0)
        influence_ids = weights_attr.getExistingArrayAttributeIndices()

        infPlug = om2.MPlug(weights_attr)

        for index in influence_ids:
            infPlug.selectAncestorLogicalIndex(index, weights_attr.attribute())
            influence = influences[index]
            value = infPlug.asDouble()
            if prune and value <= 0.0:
                continue
            weights.append([influence, value])
        data.append([vert, weights])

    return data
Ejemplo n.º 23
0
def bindToSkin(meshPaths, skinIndex, skinWeight, skinJnts, numMaxInfluences):
    asl = om.MSelectionList()
    asl.clear()
    jntNames = [sj.name for sj in skinJnts]
    for sj in skinJnts:
        m = om.MMatrix(sj.bindPose.tolist())
        m = om.MTransformationMatrix(m)
        om.MFnTransform(sj.path).setTransformation(m)
        asl.add(sj.path)
    offset = 0
    for meshPath in meshPaths:
        mesh = om.MFnMesh(meshPath)
        meshName = om.MFnDagNode(mesh.parent(0)).name()
        skinNode = findSkinCluster(meshPath)
        if skinNode:
            cmds.skinCluster(meshName, edit=True, unbind=True)
        sl = om.MSelectionList(asl)
        sl.add(meshPath)
        om.MGlobal.setActiveSelectionList(sl)
        meshName = om.MFnDagNode(mesh.parent(0)).name()
        skinName = cmds.skinCluster(maximumInfluences=numMaxInfluences,
                                    name=meshName + 'Cluster',
                                    toSelectedBones=True)[0]
        skinObj = om.MGlobal.getSelectionListByName(skinName).getDependNode(0)
        skin = oma.MFnSkinCluster(skinObj)
        vertexIndices = om.MIntArray(mesh.numVertices, 0)
        for i in xrange(mesh.numVertices):
            vertexIndices[i] = i
        singleIndexedComp = om.MFnSingleIndexedComponent()
        vertexComp = singleIndexedComp.create(om.MFn.kMeshVertComponent)
        singleIndexedComp.addElements(vertexIndices)
        infDags = skin.influenceObjects()
        numInfDags = len(infDags)
        infIndices = om.MIntArray(numInfDags, 0)
        for i in xrange(numInfDags):
            infIndices[i] = i
        weights = om.MDoubleArray(mesh.numVertices * numInfDags, 0)
        for v in xrange(mesh.numVertices):
            for j, w in zip(skinIndex[offset + v], skinWeight[offset + v]):
                if j >= 0:
                    weights[v * numInfDags + j] = w
        skin.setWeights(meshPath, vertexComp, infIndices, weights)
        offset += mesh.numVertices
        skin.findPlug('deformUserNormals', True).setBool(False)
Ejemplo n.º 24
0
def get_skin_cluster_weights(mesh, skin_cluster):

    sl = OpenMaya.MSelectionList()

    # get mesh dag path
    sl.add(mesh)
    mesh_dag = sl.getDagPath(0)

    # get skin
    sl.add(skin_cluster)
    mfn_skin = sl.getDependNode(1)

    # we just pass in an empty MObject to return all weights
    components = OpenMaya.MObject()

    # get weights
    mfn_skin = OpenMayaAnim.MFnSkinCluster(mfn_skin)
    weights, influence_count = mfn_skin.getWeights(mesh_dag, components)

    return weights
Ejemplo n.º 25
0
def getSkinFn():
    sel = om.MGlobal.getActiveSelectionList()
    meshDag = sel.getDagPath(0)

    meshDag.extendToShape()
    selList = om.MSelectionList()
    selList.add(meshDag)
    shapeObj = selList.getDependNode(0)
    dagIter =  om.MItDependencyGraph(shapeObj, om.MItDependencyGraph.kDownstream, om.MItDependencyGraph.kPlugLevel)
    skinFn = None
    while not dagIter.isDone():
        currentItem = dagIter.currentNode()
        if currentItem.hasFn(om.MFn.kSkinClusterFilter):
            skinFn = oma.MFnSkinCluster(currentItem)
        dagIter.next()

    vertIter = om.MItMeshVertex(shapeObj)
    influences = skinFn.influenceObjects()
    print len(influences)
    while not vertIter.isDone():
        weights =  skinFn.getWeights(meshDag, vertIter.currentItem())
        vertIter.next()
Ejemplo n.º 26
0
def import_json_weights(file_path, skin, mesh_key, **kwargs):
    """Apply skin weights from a json file to specified geometry.

    Args:
        file_path: Full file path to the JSON skin weights file
        skin: Skin clusters to apply weight data to
        mesh_key: Mesh name to evaluate and apply data to
        **kwargs: Currently unavailable

    Returns:
        None
    """
    with open(file_path, 'r') as fp:
        weight_data = json.load(fp)

    mesh_vert_count = cmds.polyEvaluate(mesh_key, v=True)
    file_vert_count = len(weight_data[mesh_key])
    if mesh_vert_count != file_vert_count:
        LOG.warning(
            'Weight file has a different point count than the current geometry: {0}--{1}:{2}'
            .format(mesh_key, mesh_vert_count, file_vert_count))
        return

    skin_influences = set([
        x.fullPathName() for x in oma2.MFnSkinCluster(skin).influenceObjects()
    ])
    file_influences = set([y[0] for x in weight_data[mesh_key] for y in x[1]])
    if skin_influences != file_influences:
        missing_in_file = skin_influences.difference(file_influences)
        missing_in_skin = file_influences.difference(skin_influences)
        if missing_in_skin:
            LOG.warning(
                'Skin is missing influences: {}'.format(*missing_in_skin))
        elif missing_in_file:
            LOG.warning('Weight file is missing influences: {}'.format(
                *missing_in_file))

    set_weights(skin, weight_data[mesh_key])
Ejemplo n.º 27
0
def flood_skin_cluster_influence_weights(mesh, skin_cluster, influence,
                                         weight):
    """
    TODO/wip
    """
    sl = OpenMaya.MSelectionList()

    sl.add(mesh)
    sl.add(skin_cluster)

    mesh_dag = sl.getDagPath(0)
    m_skin = sl.getDependNode(1)
    mfn_skin = OpenMayaAnim.MFnSkinCluster(m_skin)

    component = OpenMaya.MFnSingleIndexedComponent().create(
        OpenMaya.MFn.kMeshVertexComponent)

    # TODO find this
    influence_index = 0

    mfn_skin.setWeights(mesh_dag, component, influence_index, weight)

    return True
Ejemplo n.º 28
0
def get_skin_cluster_weights(mesh, skin_cluster):
    """Get skin cluster weights via MFnSkinCluster.

    TODO check that mesh is deformed by skin cluster.
    TODO options for selective influences.

    Weights are returned as a list of lists, one per influence,
    containing weights for all points.

    """
    sl = OpenMaya.MSelectionList()

    # get objects
    sl.add(mesh)
    mesh_dag = sl.getDagPath(0)

    sl.add(skin_cluster)
    m_skin = sl.getDependNode(1)

    # we just pass in an empty MObject to return all weights
    components = OpenMaya.MObject()

    # get weights
    m_skin = OpenMayaAnim.MFnSkinCluster(m_skin)
    weights, influence_count = m_skin.getWeights(mesh_dag, components)

    # slice weights per influence
    #     mesh_fn = OpenMaya.MFnMesh(mesh_dag)
    #     point_count = mesh_fn.numFaceVertices

    weights = list(weights)

    sliced_weights = [
        weights[i::influence_count] for i in range(influence_count)
    ]

    return sliced_weights
Ejemplo n.º 29
0
        jointWeights.append(weight)
    weightList.append(jointWeights)
    mFnTransform.setTranslation(world, om.MSpace.kWorld)

    if jntParent:
        cmds.parent(jointList[index], jntParent[0])
    if jntChild:
        cmds.parent(jntChild[0], jointList[index])

#Set join weight to geometry
geoSkinCluster = cmds.skinCluster(jointList, geometry)[0]
skinMSelection = om.MSelectionList()
skinMSelection.add(geoSkinCluster)
skinMObject = skinMSelection.getDependNode(0)

mfnSkinCluster = oma.MFnSkinCluster(skinMObject)

#Vertex components
vertexIndexList = range(len(geoPosition))
mfnIndexComp = om.MFnSingleIndexedComponent()
vertexComp = mfnIndexComp.create(om.MFn.kMeshVertComponent)
mfnIndexComp.addElements(vertexIndexList)

#influences
influenceObjects = mfnSkinCluster.influenceObjects()
influenceList = om.MIntArray()
for eachInfluenceObject in influenceObjects:
    currentIndex = mfnSkinCluster.indexForInfluenceObject(eachInfluenceObject)
    influenceList.append(currentIndex)

#weights
Ejemplo n.º 30
0
def sang(chue_tem_file,
         satsuan_ok=1,
         chai_kraduk=True,
         chai_bs=True,
         chai_watsadu=True,
         lok_tex=False,
         thangmot=False):
    t0 = time.time()  # 開始
    print('"%s"へのエクスポート開始' % chue_tem_file)
    chue_path_file = os.path.dirname(chue_tem_file)
    shoki = os.path.join(os.path.dirname(__file__), 'asset', 'model00.pmx')
    pmx_model = mmdio.pmx.load(shoki)  # 初期のpmxモデル
    # もっと速くするために予めappendメソッドを準備しておく
    model_vtx_ap = pmx_model.vertices.append  # 頂点
    model_face_ap = pmx_model.faces.append  # 面
    model_bon_ap = pmx_model.bones.append  # 骨
    model_mat_ap = pmx_model.materials.append  # 材質
    model_morph_ap = pmx_model.morphs.append  # モーフ
    model_dis1_ap = pmx_model.display[1].data.append  # 表示ょの表示枠
    model_dis2_ap = pmx_model.display[2].data.append  # 可動域の表示枠
    if (thangmot):
        lis_chue_nod_poly = mc.filterExpand(mc.ls(transforms=1),
                                            selectionMask=12)
        if (lis_chue_nod_poly == None):  # ポリゴンが全然ない場合
            print('このシーンの中にポリゴンはありません')
            return
    else:
        lis_chue_nod_poly = mc.filterExpand(mc.ls(transforms=1, selection=1),
                                            selectionMask=12)
        if (lis_chue_nod_poly == None):  # 選択されているポリゴンが一つもない場合
            print('ポリゴンは選択せれていません')
            return
    print('エクスポートするポリゴン:%s' % lis_chue_nod_poly)

    lis_chue_nod_shp = []  # 全てのシェープのノードを収めるリスト
    lis_chue_nod_skin = []  # ポリゴンに使う全てのスキンのノードを収めるリスト
    lis_chue_tex = []  # テクスチャの名前を収めるリスト
    lis_matrix_mun = [0]

    for chue_nod_poly in lis_chue_nod_poly:
        # このポリゴンのシェープのノード
        chue_nod_shp = mc.listRelatives(chue_nod_poly,
                                        shapes=True,
                                        fullPath=True)[0]
        lis_chue_nod_shp.append(chue_nod_shp)
        # 骨もエクスポートすると選択した場合
        if (chai_kraduk):
            for chue_nod_skin in mc.ls(typ='skinCluster'):  # このポリゴンに使うスキンのノード
                # このスキンのノードに接続されているシェープのノードは、このホリゴンのシェープのノードに接続していれば、このスキンを使う
                if (pm.PyNode(chue_nod_shp).name()
                        in mc.skinCluster(chue_nod_skin,
                                          query=True,
                                          geometry=True)):
                    lis_chue_nod_skin.append(chue_nod_skin)
                    break
            # このポリゴンと接続されているスキンがない場合
            else:
                lis_chue_nod_skin.append(0)

    if (chai_kraduk):  # ここで骨を作成しておく
        dic_chue_nod_kho = {'全ての親': 0}  # 一番外のジョイント
        i_kho = 1  # ジョイントの順番をカウントする
        for k in mc.ls(typ='joint', long=True):
            # このジョイントがすでに作成された場合、スキップする
            if (k in dic_chue_nod_kho):
                continue
            # 使用するスキンのノードと接続されているかどうか
            for chue_nod_skin in lis_chue_nod_skin:
                if (chue_nod_skin and k in [
                        pm.PyNode(x).fullPath() for x in mc.skinCluster(
                            chue_nod_skin, query=True, influence=True)
                ]):
                    break
            # 接続されていない場合、このジョイントはスキップ
            else:
                continue
            # 親ジョイントを探す
            parent = mc.listRelatives(k, parent=True, fullPath=True)
            if (parent):  # 親ジョイントがある場合
                pp = ['']
                for p in parent[0].split('|')[1:]:
                    pp.append(p)
                    pj = '|'.join(pp)
                    if (mc.nodeType(pj) == 'joint'):
                        parent = pj
                        break
                else:
                    parent = k
            else:
                parent = k  # 親がない場合、このジョイントそのもの
            # その親がすでに作られた場合、スキップする
            if (parent in dic_chue_nod_kho):
                continue
            # まだないければ、このジョイントを子ジョイントと共に新しく追加する
            lis_child = mc.listRelatives(parent,
                                         allDescendents=True,
                                         fullPath=True)
            lis_cp = [parent]  # 親と全ての子のジョイントを収めるリスト
            if (lis_child):
                lis_cp += list(reversed(lis_child))
            # 親と子のジョイントの名前を全部収める
            for j, chue_nod_kho in enumerate(lis_cp):
                dic_chue_nod_kho[chue_nod_kho] = i_kho + j
            for chue_nod_kho in lis_cp:
                # ボーンを作って初期値を与える
                bone = mmdio.pmx.Bone()
                bone.name = chue_nod_kho.split('|')[
                    -1]  # ジョイントのノードの名前をボーンの名前に使う
                bone.isRotatable = True  # 全てのボーンは回転可能
                bone.isMovable = False  # 親のないボーンだけ移動可能
                bone.visible = True  # 全てのボーン表示
                bone.isControllable = True  # 全てのボーンは操作できる
                bone.isIK = False  # IKは使わない
                bone.hasAdditionalRotate = False  # 回転付与
                bone.hasAdditionalLocation = False  # 移動付与
                bone.transAfterPhis = False  # 物理後

                nod_kho = pm.PyNode(chue_nod_kho)  # このジョイントのノード
                p = mc.xform(chue_nod_kho, query=True, t=True,
                             ws=True)  # このジョイントの位置
                bone.location = [
                    p[0] * satsuan_ok, p[1] * satsuan_ok,
                    -1 * p[2] * satsuan_ok
                ]
                try:
                    chue_parent = nod_kho.getParent().fullPath()
                    bone.parent = dic_chue_nod_kho[chue_parent]
                except:
                    bone.parent = 0
                    bone.isMovable = True
                child = nod_kho.getChildren()
                if (len(child) == 1):
                    bone.displayConnection = dic_chue_nod_kho[
                        child[0].fullPath()]
                else:
                    bone.displayConnection = -1

                jo = mc.getAttr(chue_nod_kho + '.jointOrient')[0]
                mm = lis_matrix_mun[bone.parent]
                if (jo == (0, 0, 0)):
                    lis_matrix_mun.append(mm)
                else:
                    mm *= 1
                    if (mm):
                        mm *= om.MEulerRotation(math.radians(jo[0]),
                                                math.radians(jo[1]),
                                                math.radians(
                                                    jo[2])).asMatrix()
                    else:
                        mm = om.MEulerRotation(math.radians(jo[0]),
                                               math.radians(jo[1]),
                                               math.radians(jo[2])).asMatrix()
                    lis_matrix_mun.append(mm)

                if (mm):
                    x_axis = [
                        mm.getElement(0, 0),
                        mm.getElement(0, 1), -mm.getElement(0, 2)
                    ]
                    z_axis = [
                        mm.getElement(2, 0),
                        mm.getElement(2, 1), -mm.getElement(2, 2)
                    ]

                    bone.localCoordinate = mmdio.pmx.Coordinate(x_axis, z_axis)

                model_bon_ap(bone)

                # 子を持っているジョイントだけを表示枠に入れる
                if (child):
                    model_dis2_ap((0, i_kho))
                i_kho += 1

    lis_xyz = []  # 頂点の位置を収めるリスト
    lis_u = []  # 頂点のuvを収めるリスト
    lis_v = []
    lis_norm = []  # 頂点の法線を収めるリスト
    lis_lis_lis_lek_chut_mai = []
    dic_tup_chut = {}  # 頂点の新しい番号と繋ぐ辞書
    lai_lek_chut = 0
    lai_lek_xyz = 0
    lai_lek_uv = 0
    lai_lek_norm = 0
    i_poly = 0  # ポリゴンの順番
    for chue_nod_poly in lis_chue_nod_poly:
        if (chai_kraduk):
            chue_nod_skin = lis_chue_nod_skin[i_poly]
            chue_nod_shp = lis_chue_nod_shp[i_poly]
            if (chue_nod_skin):
                dic_kho = {}  # ジョイントの番号とジョイントの名前の辞書
                for ii, chue_nod_kho in enumerate(
                        mc.skinCluster(chue_nod_skin,
                                       query=True,
                                       influence=True)):
                    dic_kho[ii] = dic_chue_nod_kho[pm.PyNode(
                        chue_nod_kho).fullPath()]

                # ジョイントとポリゴンの接続される重みを取得する
                selelis = om.MSelectionList()
                selelis.add(chue_nod_skin)
                obj_skin = selelis.getDependNode(0)
                fn_skin = oma.MFnSkinCluster(obj_skin)
                selelis = om.MSelectionList()
                selelis.add(chue_nod_shp)
                dagpath_mesh = selelis.getDagPath(0)
                path_influ = fn_skin.influenceObjects()
                n_influ = len(path_influ)
                arr_index_influ = om.MIntArray(range(n_influ))

                fn_compo = om.MFnSingleIndexedComponent()
                compo = fn_compo.create(om.MFn.kMeshVertComponent)
                # 重みのリストができた。長さはジョイント数×頂点数
                lis_namnak = fn_skin.getWeights(dagpath_mesh, compo,
                                                arr_index_influ)

        if (chai_bs):
            w_doem = []  # 元の重みの値を収めるリスト
            # このポリゴンに接続しているブレンドシェープのノードだけ取る
            lis_chue_nod_bs = []
            for chue_nod_bs in mc.ls(typ='blendShape'):
                # これがこのブレンドシェープに接続しているポリゴンであるかどうかチェック
                if (pm.PyNode(chue_nod_shp).name()
                        not in mc.blendShape(chue_nod_bs,
                                             query=True,
                                             geometry=True)):
                    continue  # 違ったらスキップ
                try:
                    ww = mc.getAttr(chue_nod_bs + '.w[*]')  # 元の重みを収めておく
                except:
                    ww = []  # 空っぽのブレンドシェープのノードの場合、エラーが出る
                    continue
                if (type(ww) == float):
                    ww = [ww]  # 一つしかない場合は返り値がリストにはならないので、全部リストにしておく
                w_doem.append(ww)
                mc.setAttr(chue_nod_bs + '.w[*]',
                           *[0] * len(ww))  # まずは全部の重みを0にしておく
                lis_chue_nod_bs.append(chue_nod_bs)

        # このポリゴンの頂点の位置
        selelis = om.MSelectionList()
        selelis.add(chue_nod_shp)
        fnmesh = om.MFnMesh(selelis.getDagPath(0))
        lis_xyz_nai_poly = fnmesh.getPoints(space=om.MSpace.kWorld)
        lis_xyz.extend(lis_xyz_nai_poly)
        lis_n_chut_nai_na, lis_lek_xyz = fnmesh.getVertices()

        # 頂点の法線
        lis_norm_nai_poly = fnmesh.getNormals(space=om.MSpace.kWorld)
        lis_norm.extend(lis_norm_nai_poly)
        lis_lek_norm = fnmesh.getNormalIds()[1]

        # 頂点のuv
        lis_u_nai_poly, lis_v_nai_poly = fnmesh.getUVs()
        lis_u.extend(lis_u_nai_poly)
        lis_v.extend(lis_v_nai_poly)
        lis_lek_uv = fnmesh.getAssignedUVs()[1]

        # その面に構成する三角形の数と頂点
        lis_n_samliam_nai_na, lis_lek_xyz_nai_na = fnmesh.getTriangles()
        lai_lek_samliam_nai_na = 0

        lis_chue_bs = []
        if (chai_bs):
            lis_xyz_bs = []  # 移動した後の頂点の位置を収めるリスト
            lis_luean_bs = []
            lis_luean_bs_ap = []
            for i_bs, chue_nod_bs in enumerate(lis_chue_nod_bs):
                n_bs_nai_nod = len(w_doem[i_bs])  # そのノードにある全てのブレンドシェープ
                # 一つずつブレンドシェープを処理する
                for i, bs in enumerate(
                        mc.listAttr(chue_nod_bs + '.w', multi=True)):
                    # 他は全部0にしておいて、そのブレンドシェープ一つだけ1にする
                    ww = [0] * n_bs_nai_nod
                    ww[i] = 1
                    mc.setAttr(chue_nod_bs + '.w[*]', *ww)
                    # 移動した後の頂点の位置
                    xyz_bs = fnmesh.getPoints(space=om.MSpace.kWorld)
                    lis_xyz_bs.append(xyz_bs)
                    lis_chue_bs.append(bs)
                    luean_bs = []
                    lis_luean_bs.append(luean_bs)
                    lis_luean_bs_ap.append(luean_bs.append)
            # 重みを元に戻す
            for i_bs, chue_nod_bs in enumerate(lis_chue_nod_bs):
                mc.setAttr(chue_nod_bs + '.w[*]', *w_doem[i_bs])

        n_bs = len(lis_chue_bs)
        lis_lis_lek_chut_mai_nai_poly = []
        i_chut = 0
        for n_samliam_nai_na, n_chut_nai_na in zip(lis_n_samliam_nai_na,
                                                   lis_n_chut_nai_na):
            # その面の三角形の数と、その面の頂点の数
            dic_lai_lek = {}
            for j in range(n_chut_nai_na):
                lek_xyz = lis_lek_xyz[i_chut]
                lek_norm = lis_lek_norm[i_chut]
                lek_uv = lis_lek_uv[i_chut]
                tup_chut = (lek_xyz + lai_lek_xyz, lek_norm + lai_lek_norm,
                            lek_uv + lai_lek_uv)
                if (tup_chut in dic_tup_chut):
                    lek_chut_mai = dic_tup_chut[tup_chut]
                else:
                    lek_chut_mai = lai_lek_chut
                    dic_tup_chut[tup_chut] = lek_chut_mai

                    # スキンと接続している場合、重みの値を取る
                    bowe = mmdio.pmx.BoneWeight()
                    if (chai_kraduk and chue_nod_skin):
                        n_kho = len(dic_kho)  # ジョイントの数
                        w = []  # [ノード名, 重み]リストを収めるリスト
                        # 重みのリストから重みの値を取る。長さはn_kho
                        for i_namnak, namnak in enumerate(
                                lis_namnak[lek_xyz * n_kho:(lek_xyz + 1) *
                                           n_kho]):
                            # 重みが小さすぎないジョイントの[ノード名, 重み]だけ取る
                            if (namnak > 0.001):
                                w.append([dic_kho[i_namnak], namnak])

                        if (len(w) > 3):  # 4つ以上ある場合
                            if (len(w) > 4):  # 4つだけ取る
                                w.sort(key=f_riang_namnak, reverse=1)
                                w = w[:4]
                            w_ruam = w[0][1] + w[1][1] + w[2][1] + w[3][
                                1]  # この4の重みの足し算
                            ww0 = w[0][1] / w_ruam
                            ww1 = w[1][1] / w_ruam
                            ww2 = w[2][1] / w_ruam
                            ww3 = w[3][1] / w_ruam
                            bowe.bones = [w[0][0], w[1][0], w[2][0], w[3][0]]
                            bowe.weights = [ww0, ww1, ww2, ww3]
                            bowe.type = mmdio.pmx.BoneWeight.BDEF4
                        elif (len(w) == 3):
                            w_ruam = w[0][1] + w[1][1] + w[2][1]
                            ww0 = w[0][1] / w_ruam
                            ww1 = w[1][1] / w_ruam
                            ww2 = w[2][1] / w_ruam
                            bowe.bones = [w[0][0], w[1][0], w[2][0], -1]
                            bowe.weights = [ww0, ww1, ww2, 0.]
                            bowe.type = mmdio.pmx.BoneWeight.BDEF4
                        elif (len(w) == 2):
                            ww0 = w[0][1] / (w[0][1] + w[1][1])
                            bowe.bones = [w[0][0], w[1][0]]
                            bowe.weights = [ww0]
                            bowe.type = mmdio.pmx.BoneWeight.BDEF2
                        elif (len(w) == 1):
                            bowe.bones = [w[0][0]]
                            bowe.type = mmdio.pmx.BoneWeight.BDEF1
                        else:
                            bowe.bones = [0]
                            bowe.type = mmdio.pmx.BoneWeight.BDEF1
                    # スキンに接続していない場合は全部一番外のジョイントのノードに繋ぐ
                    else:
                        bowe.bones = [0]
                        bowe.type = mmdio.pmx.BoneWeight.BDEF1

                    # 取得した頂点データからモデルの頂点のリストに追加
                    vtx = mmdio.pmx.Vertex()
                    p = lis_xyz[lek_xyz + lai_lek_xyz]
                    vtx.co = [
                        p[0] * satsuan_ok, p[1] * satsuan_ok,
                        -p[2] * satsuan_ok
                    ]
                    nm = lis_norm[lek_norm + lai_lek_norm]
                    vtx.normal = [nm[0], nm[1], -nm[2]]
                    vtx.uv = [
                        lis_u[lek_uv + lai_lek_uv],
                        1. - lis_v[lek_uv + lai_lek_uv]
                    ]
                    vtx.weight = bowe
                    vtx.edge_factor = 1.
                    model_vtx_ap(vtx)  # モデルの頂点のリストに追加

                    for i_bs in range(n_bs):
                        p1 = lis_xyz_bs[i_bs][lek_xyz]
                        po = [(p1[0] - p[0]) * satsuan_ok,
                              (p1[1] - p[1]) * satsuan_ok,
                              (p[2] - p1[2]) * satsuan_ok]
                        # 位置の変更が起きる頂点だけ取る
                        if (po[0]**2 + po[1]**2 + po[2]**2 > 0):
                            vmoffset = mmdio.pmx.VertexMorphOffset()
                            vmoffset.index = lai_lek_chut
                            vmoffset.offset = po
                            lis_luean_bs_ap[i_bs](vmoffset)
                    lai_lek_chut += 1

                dic_lai_lek[lek_xyz + lai_lek_xyz] = lek_chut_mai
                i_chut += 1

            lis_lek_chut_mai_nai_samliam = []
            for j in range(lai_lek_samliam_nai_na * 3,
                           (lai_lek_samliam_nai_na + n_samliam_nai_na) * 3, 3):
                for jj in range(3):
                    lek_xyz = lis_lek_xyz_nai_na[j + 2 - jj]
                    lek_chut_mai = dic_lai_lek[lek_xyz + lai_lek_xyz]
                    lis_lek_chut_mai_nai_samliam.append(lek_chut_mai)
            lai_lek_samliam_nai_na += n_samliam_nai_na
            lis_lis_lek_chut_mai_nai_poly.append(lis_lek_chut_mai_nai_samliam)

        # 準備しておいたブレンドシェープのデータからモーフを作成する
        if (chai_bs):
            for i_morph, (chue_bs,
                          luean_bs) in enumerate(zip(lis_chue_bs,
                                                     lis_luean_bs)):
                morph = mmdio.pmx.VertexMorph(name=chue_bs,
                                              name_e=chue_bs,
                                              category=4)
                morph.offsets = luean_bs
                model_morph_ap(morph)
                model_dis1_ap((1, i_morph))

        lai_lek_xyz += len(lis_xyz_nai_poly)
        lai_lek_norm += len(lis_norm_nai_poly)
        lai_lek_uv += len(lis_u_nai_poly)
        lis_lis_lis_lek_chut_mai.append(lis_lis_lek_chut_mai_nai_poly)
        i_poly += 1

    # 材質を使う場合
    if (chai_watsadu):
        i_tex = 0  # テクスチャの番号
        i_mat = 0  # 材質の番号
        for chue_mat in mc.ls(materials=True):
            # sgと繋がっている材質だけ取る
            liscon = mc.listConnections(chue_mat + '.outColor')
            if (not liscon):
                continue  # sgと繋がっていない材質はスキップ
            sg = liscon[0]
            lis_lek_na_nai_mat = mc.sets(sg, query=True)  # この材質を使っている面のリスト
            if (not lis_lek_na_nai_mat):
                if (len(liscon) > 1):
                    sg = liscon[1]
                    lis_lek_na_nai_mat = mc.sets(sg, query=True)
                # 全然使われていない場合、この材質をスキップ
                if (not lis_lek_na_nai_mat):
                    continue

            n_chut_nai_mat = 0  # この面の中の頂点の数
            for na_nai_mat in lis_lek_na_nai_mat:
                if ('[' in na_nai_mat):  # ただこのポリゴンの面の一部だけ材質が使われる場合
                    # ポリゴンの名前と、最初の面と最後の面の番号
                    chue_nod_poly, lek_na_roem, lek_na_chop = re.findall(
                        r'(\w+).f\[(\d+):?(\d+)?]', na_nai_mat)[0]
                    lek_na_roem = int(lek_na_roem)  # 最初の面の番号
                    if (lek_na_chop == ''):  # ただ一面しかない場合
                        lek_na_chop = lek_na_roem
                    else:
                        lek_na_chop = int(lek_na_chop)  # 最後の面の番号
                else:  # このポリゴン全体がこの材質を使う場合
                    chue_nod_poly = mc.listRelatives(na_nai_mat,
                                                     parent=True)[0]
                    lek_na_roem = 0
                    lek_na_chop = mc.polyEvaluate(chue_nod_poly, face=True) - 1
                # 選択されたポリゴンのリストの中にある場合、そのポリゴンの番号を取る
                if (chue_nod_poly in lis_chue_nod_poly):
                    lek_nod_poly = lis_chue_nod_poly.index(chue_nod_poly)
                # このリストにない場合、無視する
                else:
                    continue
                for lek_na in range(lek_na_roem,
                                    lek_na_chop + 1):  # 頂点の番号をモデルの面のリストに追加する
                    lis_lek_chut_nai_na = lis_lis_lis_lek_chut_mai[
                        lek_nod_poly][lek_na]
                    for ii in range(0, len(lis_lek_chut_nai_na), 3):
                        model_face_ap(lis_lek_chut_nai_na[ii:ii + 3])
                        n_chut_nai_mat += 3

            # 選択されているポリゴンの中で使われていない材質は無視する
            if (n_chut_nai_mat == 0):
                continue
            if (mc.objExists(chue_mat + '.namae')):
                namae = mc.getAttr(chue_mat + '.namae')
            else:
                namae = '材質%d' % (i_mat + 1)
            # 材質を作成して、まずは初期値を与える
            mat = mmdio.pmx.Material()
            mat.name = namae
            mat.name_e = chue_mat
            mat.diffuse = [1, 1, 1, 1]
            mat.specular = [0, 0, 0, 0.5]
            mat.ambient = [0.5, 0.5, 0.5]
            mat.edge_color = [0, 0, 0, 1]
            mat.edge_size = 1
            mat.texture = -1
            mat.sphere_texture = -1
            mat.sphere_texture_mode = 0
            mat.is_shared_toon_texture = False
            mat.toon_texture = -1
            mat.comment = ''
            mat.vertex_count = n_chut_nai_mat
            mat.is_double_sided = True

            # 普通に使えない材質の場合、エラーが出る
            try:
                nodetype = mc.nodeType(chue_mat)  # 材質のシェーディングタイプ
                # テクスチャが使われるかどうかを調べる
                if (nodetype in ['standardSurface', 'aiStandardSurface']):
                    chue_nod_tex = mc.listConnections(chue_mat + '.baseColor')
                else:  # blinn、lambert、phongなど
                    chue_nod_tex = mc.listConnections(chue_mat + '.color')
                # ファイルのテクスチャが使われている材質の場合
                if (chue_nod_tex):
                    if (mc.nodeType(chue_nod_tex[0]) == 'file'):
                        chue_tem_file_tex = mc.getAttr(
                            chue_nod_tex[0] + '.ftn')  # このテクスチャのファイルの名前
                        # 既存のファイルの場合、これを使う
                        if (chue_tem_file_tex in lis_chue_tex):
                            mat.texture = lis_chue_tex.index(chue_tem_file_tex)
                        # まだない場合、追加する
                        else:
                            lis_chue_tex.append(chue_tem_file_tex)
                            texture = mmdio.pmx.Texture()
                            texture.path = os.path.join(chue_tem_file_tex)
                            # テクスチャのファイルをコピーすると選択しておいた場合
                            if (lok_tex):
                                chue_tex = os.path.basename(chue_tem_file_tex)
                                chue_tem_path_tex_mai = os.path.join(
                                    chue_path_file, chue_tex)
                                shutil.copyfile(chue_tem_file_tex,
                                                chue_tem_path_tex_mai)
                                texture.path = os.path.join(
                                    chue_tem_path_tex_mai)
                            pmx_model.textures.append(texture)
                            mat.texture = i_tex
                            i_tex += 1  # テクスチャの番号を数え続ける
                    else:
                        print('注意:テクスチャ%sはファイルではないため無視されます' % chue_nod_tex[0])
                    dc = [1., 1., 1.]
                # テクスチャが使われていない材質の場合、拡散色の値を使う
                else:
                    if (nodetype in ['standardSurface', 'aiStandardSurface']):
                        dc = mc.getAttr(chue_mat + '.baseColor')[0]
                    else:
                        dc = mc.getAttr(chue_mat + '.color')[0]
                    dc = [min(max(s, 0.), 1.) for s in dc]
                    mat.diffuse[:3] = dc

                if (nodetype not in ['standardSurface', 'aiStandardSurface']):
                    tran = sum(
                        mc.getAttr(chue_mat +
                                   '.transparency')[0]) / 3  # 透明度は3色の平均値を使う
                    mat.diffuse[3] = min(max(1 - tran, 0), 1.)
                    mat.ambient = [
                        min(max(s, 0.), 1.) * d for s, d in zip(
                            mc.getAttr(chue_mat + '.ambientColor')[0], dc)
                    ]
                    # blinnだけスペキュラを使う
                    if (nodetype == 'blinn'):
                        sr = min(
                            max(mc.getAttr(chue_mat + '.specularRollOff'),
                                0.1), 1.)
                        mat.specular[3] = round(
                            math.pow(2,
                                     math.log(max(sr, 0.1), 0.75) - 1))
                        mat.specular[:3] = [
                            min(max(s, 0.), 1.)
                            for s in mc.getAttr(chue_mat + '.specularColor')[0]
                        ]
                # standardSurfaceの場合
                else:
                    opa = sum(mc.getAttr(chue_mat +
                                         '.opacity')[0]) / 3  # 不透明度は3色の平均値を使う
                    mat.diffuse[3] = min(max(opa, 0.), 1.)
                    mat.specular[:3] = [
                        min(max(s, 0.), 1.)
                        for s in mc.getAttr(chue_mat + '.specularColor')[0]
                    ]
                    sr = max(mc.getAttr(chue_mat + '.specularRoughness'), 0.1)
                    mat.specular[3] = round(
                        math.pow(2,
                                 math.log(max(sr, 0.1), 0.75) - 1))
                    mat.ambient = [0, 0, 0]  # standardSurfaceの場合にアンビアントがないので
            except:
                print('材質%sに問題が見つかったようです' % chue_mat)

            model_mat_ap(mat)  # モデルの材質のリストに収める
            i_mat += 1

    # 材質を使わないと選択した場合、全部同じ材質にする
    else:
        n_chut_nai_mat = 0
        for lis_lis_lek_chut_nai_poly in lis_lis_lis_lek_chut_mai:
            for lis_lek_chut_nai_na in lis_lis_lek_chut_nai_poly:
                n_chut_nai_na = len(lis_lek_chut_nai_na)
                n_chut_nai_mat += n_chut_nai_na
                for i in range(0, n_chut_nai_na, 3):
                    model_face_ap(lis_lek_chut_nai_na[i:i + 3])

        mat = mmdio.pmx.Material()
        mat.name = '材質1'
        mat.name_e = ''
        mat.diffuse = [0.5, 0.5, 0.5, 1]
        mat.specular = [0.5, 0.5, 0.5, 0.5]
        mat.ambient = [0.25, 0.25, 0.25]
        mat.edge_color = [0, 0, 0, 1]
        mat.edge_size = 1
        mat.texture = -1
        mat.sphere_texture = -1
        mat.sphere_texture_mode = 0
        mat.is_shared_toon_texture = False
        mat.toon_texture = -1
        mat.comment = ''
        mat.vertex_count = n_chut_nai_mat
        mat.is_double_sided = True
        model_mat_ap(mat)

    chue_model = os.path.basename(chue_tem_file).split('.')[0]
    pmx_model.name = chue_model
    pmx_model.name_e = chue_model
    if (not pmx_model.display[2].data):
        pmx_model.display.pop()

    mmdio.pmx.save(chue_tem_file, pmx_model)
    mc.select(lis_chue_nod_poly)
    print('"%s"へエクスポート完了。\n%.2f秒かかりました' % (chue_tem_file, time.time() - t0))