Beispiel #1
0
def skinClusterData(skinCluster, meshPath, component):
    # now if we have a skincluster lets fill in the blanks we had before
    selectionList2 = MGlobal.getSelectionListByName(skinCluster[0])
    skinObj = selectionList2.getDependNode(0)
    skinFn = MFnSkinCluster(skinObj)
    indexMap = {y: x for x, y in getJointIndexMap(skinCluster[0]).items()}
    jointWeights = skinFn.getWeights(meshPath, component)[0]
    return indexMap, jointWeights
Beispiel #2
0
def getDag(name):
	sel_list = omg.getSelectionListByName(name)
	print(sel_list)
	#
	'''
	iterator = om.MItSelectionList(sel_list, om.Mfn.kDagNode)
	dagPath = om.MDagPath()
	result = []
	if not iterator.isDone():
		iterator.getDagPath(dagPath)
		result = [dagPath]
'''
	return result
Beispiel #3
0
def exportAllMeshes(source, target, isSkinned=False):
    if source:
        cmds.file(source, open=True, force=True)

    if isSkinned:
        skinnedJoints = exportSkeleton(target)
    else:
        skinnedJoints = []

    with open(target, 'wb') as fh:
        # write version
        fh.write(b'MSH\0MAYA')

        meshes = cmds.ls(type='mesh', ni=True, l=True)

        # write mesh count
        fh.write(struct.pack('<I', len(meshes)))

        for mesh in meshes:
            # write mesh name
            name = mesh.encode('utf8')
            fh.write(struct.pack('<I', len(name)))
            fh.write(name)

            # write material name
            try:
                lambert = cmds.listConnections(cmds.listConnections(
                    mesh, type='shadingEngine'),
                                               d=False,
                                               s=True,
                                               type='lambert')[0]
            except:
                lambert = ''
            material = lambert.encode('utf8')
            fh.write(struct.pack('<I', len(material)))
            fh.write(material)

            # get API handles to object name
            selectionList = MGlobal.getSelectionListByName(mesh)
            dagPath = selectionList.getDagPath(0)
            polyIterator = MItMeshPolygon(dagPath)
            meshFn = MFnMesh(dagPath)

            jointWeights = []
            logicalIndexMap = {}
            physicalToLogicalMap = {}

            if isSkinned:
                # if we flag the mesh as skinned lets have a look if we have a skincluster
                # some of these values are predetermined so if it turns out not to be skinned then we leave it alone
                skinCluster = cmds.ls(cmds.listHistory(mesh),
                                      type="skinCluster")
                if skinCluster:
                    meshPath, component = selectionList.getComponent(0)
                    logicalIndexMap, jointWeights = skinClusterData(
                        skinCluster, meshPath, component)
                    physicalToLogicalMap = {
                        physicalIndex: logicalIndex
                        for (physicalIndex,
                             logicalIndex) in enumerate(logicalIndexMap.keys())
                    }
                else:
                    isSkinned = False

            # extract mesh data in 1 go, uses more memory but faster to execute and I assume a duplicate of 1 mesh will fit in memory
            normals = meshFn.getNormals(MSpace.kWorld)
            tangents = meshFn.getTangents(MSpace.kWorld)
            uvSetNames = meshFn.getUVSetNames()
            colorSetNames = meshFn.getColorSetNames()

            # write attribute layout now we know all the attributes
            floatsPerVertex = 3 + 3 + 3 + len(uvSetNames) * 2 + len(
                colorSetNames) * 4 + int(isSkinned) * 8

            # num attributes
            fh.write(
                struct.pack(
                    '<I', 3 + len(uvSetNames) + len(colorSetNames) +
                    int(isSkinned) * 2))
            # write position, normal and tangent attributes: semantic & nr of floats
            fh.write(
                struct.pack('<II', VertexAttribute.Semantic.POSITION.value, 3))
            fh.write(
                struct.pack('<II', VertexAttribute.Semantic.NORMAL.value, 3))
            fh.write(
                struct.pack('<II', VertexAttribute.Semantic.TANGENT.value, 3))

            for i, n in enumerate(uvSetNames):
                assert i < 8, 'We currently only anticipated 8 texcoords, please use a color set instead.'
                fh.write(
                    struct.pack('<II',
                                VertexAttribute.Semantic.TEXCOORD0.value + i,
                                2))

            for i, n in enumerate(colorSetNames):
                fh.write(
                    struct.pack('<II',
                                VertexAttribute.Semantic.COLOR0.value + i, 4))

            if isSkinned:
                fh.write(
                    struct.pack('<II',
                                VertexAttribute.Semantic.BLENDINDICES.value,
                                4))
                fh.write(
                    struct.pack('<II',
                                VertexAttribute.Semantic.BLENDWEIGHT.value, 4))

            # storage
            vertexDataHashes = {}
            vertexData = []
            indexData = []

            # pre-alloc
            uvSets = [None] * len(uvSetNames)
            colorSets = [None] * len(colorSetNames)
            vertexChunk = [0.0] * floatsPerVertex

            # walk mesh faces
            while not polyIterator.isDone():
                positions, vertexIndices = polyIterator.getTriangles(
                    MSpace.kWorld)
                # get colors and uvs for this face
                for index, n in enumerate(uvSetNames):
                    u, v = polyIterator.getUVs(n)
                    uvSets[index] = (u, v, n)
                for index, n in enumerate(colorSetNames):
                    c = polyIterator.getColors(n)
                    colorSets[index] = (c, n)
                # itr.getNormals(normals, MSpace.kWorld)
                untriangulatedVertexIndices = polyIterator.getVertices()
                localVertexIndices = {
                    j: i
                    for i, j in enumerate(untriangulatedVertexIndices)
                }

                # walk face triangulation
                for i in range(len(vertexIndices)):
                    localVertexIndex = localVertexIndices[vertexIndices[i]]
                    # build vertex data for this face-vertex
                    P = positions[i]
                    N = normals[polyIterator.normalIndex(localVertexIndex)]
                    T = tangents[polyIterator.tangentIndex(localVertexIndex)]
                    vertexChunk[:
                                9] = P.x, P.y, P.z, N.x, N.y, N.z, T.x, T.y, T.z
                    j = 9

                    for u, v, n in uvSets:
                        vertexChunk[j] = u[localVertexIndex]
                        vertexChunk[j + 1] = v[localVertexIndex]
                        j += 2

                    for c, n in colorSets:
                        C = c[localVertexIndex]
                        vertexChunk[j] = C.r
                        vertexChunk[j + 1] = C.g
                        vertexChunk[j + 2] = C.b
                        vertexChunk[j + 3] = C.a
                        j += 4

                    if isSkinned:
                        jointCount = len(logicalIndexMap)
                        weightRange = list(
                            jointWeights[vertexIndices[i] *
                                         jointCount:(vertexIndices[i] + 1) *
                                         jointCount])
                        highToLow = sorted(enumerate(weightRange),
                                           key=lambda pair: -pair[1])

                        MAX_INDICES = 4
                        padded = highToLow[:MAX_INDICES] + [
                            (0, 0.0)
                        ] * (MAX_INDICES - len(highToLow))
                        factor = sum(pair[1] for pair in padded)
                        if factor:
                            factor = 1.0 / factor

                        for index, (jointId, weight) in enumerate(padded):
                            # this jointId is local to this skin-cluster,
                            # use the indexMap to extract the name and then map it to a global jointId
                            logicalIndex = physicalToLogicalMap[jointId]
                            index = logicalIndexMap[logicalIndex]
                            vertexChunk[j + index] = skinnedJoints.get(
                                index, 0)
                            vertexChunk[j + MAX_INDICES +
                                        index] = weight * factor  # normalized

                        j += MAX_INDICES * 2

                    vertex = tuple(vertexChunk)
                    hsh = hash(vertex)
                    # reuse vertex data if possible
                    n = len(vertexDataHashes)
                    vertexId = vertexDataHashes.setdefault(hsh, n)
                    if vertexId == n:
                        vertexData.append(vertex)
                    # build index buffer
                    indexData.append(vertexId)
                polyIterator.next()

            # write buffer sizes
            fh.write(
                struct.pack('<II',
                            len(vertexData) * floatsPerVertex, len(indexData)))
            # write mesh data
            for vertex in vertexData:
                fh.write(struct.pack('<%if' % floatsPerVertex, *vertex))
            fh.write(struct.pack('<%iI' % len(indexData), *indexData))