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
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
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))