コード例 #1
0
    def __init__(self, meshData, baseInfo=None):
        self._meshData = meshData
        fn = MFnMesh(meshData)

        # 頂点座標リストを生成。各要素は API 2.0 の MVector とする。
        pntArr = MFloatPointArray()
        fn.getPoints(pntArr)
        nVrts = pntArr.length()
        if baseInfo and baseInfo[0] != nVrts:
            # ベースケージと頂点数が合わない場合は無効とする。
            self._vertices = None
            return
        vertices = _NONE_LIST * nVrts
        for i in xrange(nVrts):
            p = pntArr[i]
            vertices[i] = api2_MVector(p.x, p.y, p.z)
        #_pprt(vertices)
        self._vertices = vertices

        # ベースケージの場合はトライアングル情報を構築する。
        # トライアングルリストを生成。各要素は3頂点のインデクスリストとする。
        if baseInfo:
            triangles = baseInfo[1]
            self._triRestEdges = baseInfo[2]
            self._triRestAreas = baseInfo[3]
        else:
            triCounts = MIntArray()
            triVrts = MIntArray()
            fn.getTriangles(triCounts, triVrts)
            nPlys = triCounts.length()
            #print(triCounts.length(), triVrts.length())
            triangles = []
            vi = 0
            for i in xrange(nPlys):
                for j in range(triCounts[i]):
                    triangles.append([triVrts[k] for k in range(vi, vi + 3)])
                    vi += 3
            #_pprt(triangles)
        self._triangles = triangles

        # トライアングルのエッジベクトルを計算。
        self._triEdges = [(vertices[tri[1]] - vertices[tri[0]],
                           vertices[tri[2]] - vertices[tri[1]])
                          for tri in triangles]

        # トライアングルの法線ベクトルを計算。
        self._triNrms = [(u ^ v).normalize() for u, v in self._triEdges]

        # ベースケージの場合はトライアングルの面積を計算。変形ケージでは不要。
        if not baseInfo:
            self._triAreas = [(u ^ v).length() * .5 for u, v in self._triEdges]
コード例 #2
0
def setSkinWeights(skinCluster, vertJointWeightData):
    '''
	vertJointWeightData is a list of 2-tuples containing the vertex component name, and a list of 2-tuples
	containing the joint name and weight.  ie it looks like this:
	[ ('someMesh.vtx[0]', [('joint1', 0.25), 'joint2', 0.75)]),
	  ('someMesh.vtx[1]', [('joint1', 0.2), 'joint2', 0.7, 'joint3', 0.1)]),
	  ... ]
	'''

    #convert the vertex component names into vertex indices
    idxJointWeight = []
    for vert, jointsAndWeights in vertJointWeightData:
        idx = int(vert[vert.rindex('[') + 1:-1])
        idxJointWeight.append((idx, jointsAndWeights))

    #get an MObject for the skin cluster node
    skinCluster = apiExtensions.asMObject(skinCluster)
    skinFn = MFnSkinCluster(skinCluster)

    #construct a dict mapping joint names to joint indices
    jApiIndices = {}
    _tmp = MDagPathArray()
    skinFn.influenceObjects(_tmp)
    for n in range(_tmp.length()):
        jApiIndices[str(_tmp[n].node())] = skinFn.indexForInfluenceObject(
            _tmp[n])

    weightListP = skinFn.findPlug("weightList")
    weightListObj = weightListP.attribute()
    weightsP = skinFn.findPlug("weights")

    tmpIntArray = MIntArray()
    baseFmtStr = str(
        skinCluster
    ) + '.weightList[%d]'  #pre build this string: fewer string ops == faster-ness!

    for vertIdx, jointsAndWeights in idxJointWeight:

        #we need to use the api to query the physical indices used
        weightsP.selectAncestorLogicalIndex(vertIdx, weightListObj)
        weightsP.getExistingArrayAttributeIndices(tmpIntArray)

        weightFmtStr = baseFmtStr % vertIdx + '.weights[%d]'

        #clear out any existing skin data - and awesomely we cannot do this with the api - so we need to use a weird ass mel command
        for n in range(tmpIntArray.length()):
            removeMultiInstance(weightFmtStr % tmpIntArray[n])

        #at this point using the api or mel to set the data is a moot point...  we have the strings already so just use mel
        for joint, weight in jointsAndWeights:
            if weight:
                try:
                    infIdx = jApiIndices[joint]
                except KeyError:
                    try:
                        infIdx = jApiIndices[joint.split('|')[0]]
                    except KeyError:
                        continue

                setAttr(weightFmtStr % infIdx, weight)