def _optimizeComponentList(mesh, componentList): """ Given the specified mesh and its list of components, return a list that represents the most optimized representation of the components. ex. ['vtx[10]','vtx[11]'] optimizes to ['vtx[10:11]'] """ vertices = [] faces = [] edges = [] for comp in componentList: if comp.startswith("f["): toAdd = faces elif comp.startswith("vtx["): toAdd = vertices elif comp.startswith("e["): toAdd = edges else: mel.eval('warning "Unsupported component type: %s"' % comp) continue toAdd.append("%s.%s" % (mesh, comp)) newCompList = [] if len(vertices): newComps = cmds.polyListComponentConversion(vertices, tv=True) if newComps is not None: newCompList.extend(newComps) if len(faces): newComps = cmds.polyListComponentConversion(faces, tf=True) if newComps is not None: newCompList.extend(newComps) if len(edges): newComps = cmds.polyListComponentConversion(edges, te=True) if newComps is not None: newCompList.extend(newComps) return [x.split(".")[-1] for x in newCompList]
def unfoldBandUVs(object, divisions=1, history=True): """ This definition unfolds object band UVs. :param object: Object. ( String ) :param divisions: Extrusion divisions. ( Integer ) :param history: Keep construction history. ( Boolean ) """ edgesCount = cmds.polyEvaluate(object, edge=True) edges = cmds.ls(object + ".e[0:" + str(edgesCount - 1) + "]", fl=True, l=True) cmds.select(object) cmds.polySelectConstraint(m=3, t=0x8000, w=1) cmds.polySelectConstraint(m=0) for i in range(divisions): mel.eval("GrowPolygonSelectionRegion();") bandEdges = cmds.ls(sl=True, fl=True, l=True) bandFaces = cmds.ls(cmds.polyListComponentConversion(bandEdges, fe=True, tf=True), fl=True) cmds.select(bandFaces) cmds.polyForceUV(unitize=True) cmds.polySelectConstraint(m=3, t=0x8000, sm=1) seamsEdges = cmds.ls(sl=True, fl=True, l=True) weldEdges = list(set(bandEdges).difference(set(seamsEdges))) cmds.polyMapSewMove(weldEdges) cmds.polyLayoutUV(bandFaces, scale=1, rotateForBestFit=0, layout=1) uvs = cmds.polyListComponentConversion(bandFaces, toUV=1) cmds.polyEditUV(uvs, u=1, v=0) not history and cmds.delete(object, ch=True)
def shrinkVertexSelection(vtxSel): ''' Shrink the specified vertex selection list. @param vtxSel: Vertex selection list to expand. @type vtxSel: list ''' # ========== # - Checks - # ========== # Check Vertex Selection vtxSel = mc.filterExpand(vtxSel,sm=31) if not vtxSel: raise Exception('Invalid vertex selection!') # ==================== # - Shrink Selection - # ==================== # Convert To Faces conSel = mc.polyListComponentConversion(vtxSel,fv=True,tf=True,internal=True) # Convert To Vertex newSel = mc.polyListComponentConversion(conSel,ff=True,fe=True,tv=True,internal=True) # ================= # - Return Result - # ================= return newSel
def expandVertexSelection(vtxSel,useFace=False): ''' Expand the specified vertex selection list. @param vtxSel: Vertex selection list to expand. @type vtxSel: list @param useFace: Expand the selection using face connection instead of edge connection. @type useFace: bool ''' # ========== # - Checks - # ========== # Check Vertex Selection vtxSel = mc.filterExpand(vtxSel,sm=31) if not vtxSel: raise Exception('Invalid vertex selection!') # ==================== # - Expand Selection - # ==================== conSel = [] if useFace: # Convert To Faces conSel = mc.polyListComponentConversion(vtxSel,fv=True,tf=True,internal=False) else: # Convert To Faces conSel = mc.polyListComponentConversion(vtxSel,fv=True,te=True,internal=False) # Convert To Vertex newSel = mc.polyListComponentConversion(conSel,ff=True,fe=True,tv=True,internal=False) # ================= # - Return Result - # ================= return newSel
def autoEyebrowGuidePosition(side = None, guideName = None): objectName = side + "_" + guideName sel = cmds.ls(os = 1, flatten = 1) pos = [] cluster = [] # check which type of component is selected and store the position for t in sel: i = t selType = t.split(".")[1][0] if selType == "e": vtx = cmds.polyListComponentConversion(i, fe = 1, tv = 1) cmds.select(vtx) cls = cmds.cluster() clsPos = cmds.xform(cls, query = 1, rotatePivot = 1, worldSpace = 1) pos.append(clsPos) cluster.append(cls) elif selType == "f": vtx = cmds.polyListComponentConversion(i, ff = 1, tv = 1) cmds.select(vtx) cls = cmds.cluster() clsPos = cmds.xform(cls, query = 1, rotatePivot = 1, worldSpace = 1) pos.append(clsPos) cluster.append(cls) elif selType == "v": cmds.warning("Select in another component mode! We are out of verts dude!!!") else: cmds.warning("No components selected dude!!!") # check if guide group exists if cluster: if cmds.objExists(objectName + "_TRN"): cmds.delete(objectName + "_TRN") # create the guides guides = defGuideCmds.defGuideCrv() guides.__init__(nSpans = len(cluster)-1, curveDegree = 1, offset =.2, offsetVector = [1,0,0], side = side, name = guideName, startPosition = [0,0,0], ctlSize = 10) cmds.delete("C_curve_TRN") # delete the cluster for c in cluster: cmds.delete(c) # list all the guides inside the guideName group except the curve loc = cmds.listRelatives(objectName + "_TRN", allDescendents = 1, type = "transform")[:-1] # reposition the guides at the vertices place for i, p in zip(loc, pos): cmds.xform(i, translation = p, worldSpace = 1) # mirror the guides cmds.select(loc) guides.createMirror()
def skinWeights(x=None, export=None, f=None, fileName=None): # Import/export skin weights from/to a file # x/export: 0 for import, 1 for export # f/fileName: filename under default project directory x = x or export if not (f or fileName): raise Exception, "Missing argument: fileName" if fileName: f = fileName obj = cmds.ls(sl=1) if not obj: raise Exception, "No object selected" obj = obj[0] node = None for n in cmds.listHistory(obj, f=0, bf=1): if cmds.nodeType(n) == 'skinCluster': node = n break if not node: raise Exception, "no skin cluster found" mode = "r" if x: mode = "w" f = open(cmds.internalVar(uwd=1) + f, mode) allTransforms = cmds.skinPercent(node, cmds.ls(cmds.polyListComponentConversion(obj, tv=1), fl=1), q=1, t=None) for vertex in cmds.ls(cmds.polyListComponentConversion(obj,tv=1), fl=1): if x: transforms = cmds.skinPercent(node, vertex, ib=1e-010, q=1, t=None) weights = cmds.skinPercent(node, vertex, ib=1e-010, q=1, v=1) s = "" for i in range(len(transforms)): s += str(weights[i])+"@"+transforms[i]+" " f.write(s+"\n") else: weights = {} for t in allTransforms: weights[t] = float(0) readWeights = f.readline().strip().split(" ") for i in readWeights: w = i.split("@") if w[1] in weights: weights[w[1]] = float(w[0]) w = [] for i in weights.iteritems(): w.append(i) cmds.skinPercent(node, vertex, tv=w) f.close()
def highlightPolys(self, trisOnly=False, ngonsOnly=False, quadsOnly=False): import math, sys, os import maya.cmds as cmds import maya.mel as mel faceWarningList = []; triWarningList = []; ngonWarningList = []; quadWarningList = []; originalObject = cmds.ls(selection=True) ##Convert selection to faces selectedFaces = (cmds.polyListComponentConversion( (cmds.ls (sl=1, flatten=1)), tf=True)) #print(selectedFaces) cmds.select (selectedFaces) #make list of selected faces selectedItems = (cmds.ls (flatten=True, selection=True)) lengthOfList = len(selectedItems) #print ("***Number of items in list " + str(lengthOfList)) #print(selectedItems) for i in xrange(len(selectedItems)): tempFace = selectedItems[i] cmds.select (tempFace) #print(tempFace) originalSelection = cmds.ls (sl=1, flatten=1) #print(type(originalSelection)) faceVertices = (cmds.polyListComponentConversion( originalSelection, tv=True) ) cmds.select( faceVertices ) faceVerticesFlat = cmds.ls(faceVertices, flatten = True) cmds.select( originalSelection ) #print (faceVerticesFlat) #print (selectedVertices) noOfVertices = 0 for j in xrange(len(faceVerticesFlat)): noOfVertices = 1 + noOfVertices #print(noOfVertices) if (noOfVertices != 4): faceWarningList.append(selectedItems[i]) if (noOfVertices == 3): triWarningList.append(selectedItems[i]) if (noOfVertices == 4): quadWarningList.append(selectedItems[i]) if (noOfVertices > 4): ngonWarningList.append(selectedItems[i]) #DisplayResult print("Number of Non-Quad Faces Found: " + str(len(faceWarningList))) try: self.ui.triFace.setValue(len(triWarningList)) self.ui.ngonFace.setValue(len(ngonWarningList)) except Exception, e: ##This will happen if there is no UI print( e ) print("Number of trianges: " + str( len(triWarningList) ) ) print("Number of ngons: " + str( len(ngonWarningList) ) ) print("Number of quads: " + str( len(quadWarningList) ) )
def polySelectTraverse(traversal=1): """ Grow polyComponent selection :param traversal: 0 = Off. 1 = More : will add current selection border to current selection. 2 = Less : will remove current selection border from current selection. 3 = Border : will keep only current selection border. 4 = Contiguous Edges : Add edges aligned with the current edges selected :type traversal: int """ #--- Vertex ---# result = mc.polyListComponentConversion(fv=True, tv=True) if result: mc.polySelectConstraint(pp=traversal, t=0x0001) else: #--- Edge ---# result = mc.polyListComponentConversion(fe=True, te=True) if result: mc.polySelectConstraint(pp=traversal, t=0x8000) else: #--- Face ---# result = mc.polyListComponentConversion(ff=True, tf=True) if result: mc.polySelectConstraint(pp=traversal, t=0x0008) else: #--- Uv ---# result = mc.polyListComponentConversion(fuv=True, tuv=True) if result: mc.polySelectConstraint(pp=traversal, t=0x0010)
def flatten_marvelous_shells(shells): """ Usage: flatten_marvelous_shells(mc.ls(sl=True)) """ for obj in shells: start_vert, end_vert = mc.ls( mc.polyListComponentConversion(cmds.ls(obj + ".e[0]")[0], fe=True, tv=True), fl=True ) start_scale = distance.euclidean( mc.xform(start_vert, q=True, t=True, ws=True), mc.xform(end_vert, q=True, t=True, ws=True) ) for uv in cmds.ls(obj + ".map[:]", fl=True): uv_pos = mc.polyEditUV(uv, q=True) uv_index = re.findall("\[([0-9]+)\]", uv)[0] vertex = mc.polyListComponentConversion(uv, fuv=True, tv=True)[0] mc.xform(vertex, t=[uv_pos[0]] + [0] + [uv_pos[1]], ws=True) # Finally, scale it end_scale = distance.euclidean( mc.xform(start_vert, q=True, t=True, ws=True), mc.xform(end_vert, q=True, t=True, ws=True) ) scale_by = start_scale / end_scale mc.xform(mc.ls(obj + ".vtx[:]"), s=[scale_by, scale_by, scale_by], ws=True)
def getMeshVertexData( mesh ): returnData = [] exportObject = 'bwExportObject' cmds.duplicate( mesh, n=exportObject ) cmds.polyTriangulate(exportObject) numOfFaces = cmds.polyEvaluate(exportObject, f=True ) for i in xrange(0, numOfFaces): faceSelect = exportObject + '.f[' + str(i) + ']' fVertices = [] fVertices = cmds.polyListComponentConversion(faceSelect, ff = True, tvf = True) fVertices = cmds.filterExpand(fVertices, sm = 70, ex = True) print fVertices for vertex in fVertices: faceDict = {} vName = cmds.polyListComponentConversion(vertex, fvf = True, tv = True) xyz = [] xyz = cmds.xform(vName, q = True, os = True, t = True) faceDict['x'] = round(xyz[0], 2) faceDict['y'] = round(xyz[1], 2) faceDict['z'] = round(xyz[2], 2) normal = [] normal = cmds.polyNormalPerVertex(vertex, q = True, xyz = True) faceDict['xN'] = round(normal[0], 2) faceDict['yN'] = round(normal[1], 2) faceDict['zN'] = round(normal[2], 2) # vuv = [] # vuv = cmds.polyListComponentConversion(vertex, fvf = True, tuv = True) # uvCoords = [] # uvCoords = cmds.polyEditUV(vuv[0], q = True, u = True, v = True) # faceDict['u'] = round(uvCoords[0], 2) # faceDict['v'] = round(uvCoords[0], 2) returnData.append(faceDict) cmds.delete(exportObject) return json.dumps(returnData)
def shortestPath(self): "Returns a list of adjacent vertices defining the shortest path from vertA to vertB." vertA=str(self[0]) vertB=str(self[1]) del self[2:]# make sure there are only two vertices in the list vertPath=list([vertA]) vert=str(vertA) distanceList=self.distanceList(vertB,vertA) sizeList=len(distanceList) for i in range(1,sizeList): tempList=distanceList[ sizeList-i-1 ] tempList=mc.ls( tempList, fl=True ) vertices=mc.polyListComponentConversion( vert, te=True ) vertices=mc.polyListComponentConversion( vertices, tv=True ) vertices=mc.ls( vertices, fl=True ) tempA=list([vert]) vertices=removeAll(tempA,vertices) intersectorSet=Set(vertices) intersectorSet.intersection_update(tempList) vertTempArray=list(intersectorSet) vert=str(vertTempArray[0]) vertPath.append( vert ) vertPath.append( vertB ) return vertPath
def getUVs(self): # Getting current uvset currUVSet = cmds.polyUVSet( self.name, q=True, currentUVSet=True )[0] for i, uvSet in enumerate(self.uvSets): self.uvs[uvSet] = [] # Setting uvSet temp cmds.polyUVSet( self.name, currentUVSet=True, uvSet=uvSet ) # Get uv maps uvMaps = cmds.polyListComponentConversion( self.name, ff=1, tuv=1 ) # verts = PolyFace.findWindingOrder(self.name) # print(self.vtxFaceNames) # cmds.polyListComponentConversion('pPlane2.vtxFace[2][1]', tuv=1 ) if( uvMaps ): # uvMaps = cmds.filterExpand( uvMaps, expand=True, sm=35 ) uvMaps = [cmds.polyListComponentConversion(vtxFace, tuv=1 ) for vtxFace in self.vtxFaceNames ] # Check to make sure there are uv's on this face. for uvMap in uvMaps: # Get my uvValues uvCoords = cmds.polyEditUV( uvMap, q=True ) self.uvs[uvSet].append(uvCoords) # Returning to orginal uvSet cmds.polyUVSet( self.name, currentUVSet=True, uvSet=currUVSet)
def select_inside_loop(): # get selected face loop and one inner face, convert to edges get_sel = cmds.ls(os=1,fl=1) if _cmds().is_component(get_sel) == "face": mesh = cmds.ls(sl=1,fl=1,o=1) edge_from_face = cmds.ls(cmds.polyListComponentConversion(get_sel[:-1],te=1,bo=1),fl=1) # create temp uvset for uv projection current_uvset = cmds.polyUVSet(mesh,q=1,cuv=1)[0] for uvset in cmds.polyUVSet(mesh,q=1,auv=1): if uvset == "af_tmp_select_uvset": cmds.polyUVSet(mesh,delete=1,uvSet="af_tmp_select_uvset") cmds.polyUVSet(mesh,create=1,uvSet="af_tmp_select_uvset") cmds.polyUVSet(mesh,e=1,cuv=1,uvSet="af_tmp_select_uvset") else: cmds.polyUVSet(mesh,create=1,uvSet="af_tmp_select_uvset") cmds.polyUVSet(mesh,e=1,cuv=1,uvSet="af_tmp_select_uvset") cmds.polyProjection(mesh,ch=0,type="Planar",ibd=1,md="y") cmds.polyMapCut(edge_from_face,e=0) # get inner selection cmds.select(cmds.polyListComponentConversion(get_sel[-1],tuv=1),r=1) mm.eval("polySelectBorderShell 0;ConvertSelectionToFaces;") inner = cmds.ls(sl=1,fl=1) # cleanup cmds.polyUVSet(mesh,e=1,cuv=1,uvSet=current_uvset) cmds.polyUVSet(mesh,delete=1,uvSet="af_tmp_select_uvset") cmds.delete(mesh,ch=1) # select fill cmds.select((inner+get_sel[:-1]),r=1)
def cleanupHierarchicalSubdivisionConversion(object): """ This definition cleans Maya hierarchical polygonal conversion. :param object: Object to cleanup. ( String ) """ cmds.select(object) cmds.polySelectConstraint(m=3, t=8, sz=3) cmds.polySelectConstraint(dis=True) nsidesFaces = cmds.ls(sl=True, l=True, fl=True) cmds.select(nsidesFaces) cmds.polySelectConstraint(m=3, t=1, order=True, orb=(3, 3)) cmds.polySelectConstraint(dis=True) nsideVertices = cmds.ls(sl=True, l=True, fl=True) offendingEdges = [] for vertice in nsideVertices: faces = cmds.ls(cmds.polyListComponentConversion(vertice, fv=True, tf=True), fl=True, l=True) faces = [face for face in faces if not face in nsidesFaces] if len(faces) == 2: faceEdgesA = cmds.ls(cmds.polyListComponentConversion(faces[0], ff=True, te=True), fl=True, l=True) faceEdgesB = cmds.ls(cmds.polyListComponentConversion(faces[1], ff=True, te=True), fl=True, l=True) sharedEdge = list(set(faceEdgesA).intersection(faceEdgesB)) offendingEdges.append(sharedEdge[0]) cmds.polySelectSp(offendingEdges, loop=True) cmds.polyDelEdge(cmds.ls(sl=True), cv=True, ch=True) cmds.select(object)
def findFacesInVolume(meshes, volume, contained=False): """ returns a dict containing the of faces within a given volume. if contained is True, then only faces wholly contained by the volume are returned """ meshVertsWithin = findVertsInVolume(meshes, volume) meshFacesWithin = {} for mesh, verts in meshVertsWithin.iteritems(): if not verts: continue meshFacesWithin[mesh] = [] vertNames = ["%s.vtx[%d]" % (mesh, v.id) for v in verts] if contained: faces = set(cmd.ls(cmd.polyListComponentConversion(vertNames, toFace=True), fl=True)) [ faces.remove(f) for f in cmd.ls(cmd.polyListComponentConversion(vertNames, toFace=True, border=True), fl=True) ] meshFacesWithin[mesh] = [f.split(".")[1] for f in faces] else: faces = cmd.ls(cmd.polyListComponentConversion(vertNames, toFace=True), fl=True) meshFacesWithin[mesh] = [f.split(".")[1] for f in faces] return meshFacesWithin
def run(): start = time.clock() selectedNodes = cmds.ls(sl = True, l = True) checkSelection(selectedNodes) srcPolygons = cmds.ls(cmds.polyListComponentConversion(selectedNodes[0], tf = True), l = True, fl = True) tgtPolygons = cmds.ls(cmds.polyListComponentConversion(selectedNodes[1], tf = True), l = True, fl = True) sourcePolygons = [Polygon(poly) for poly in srcPolygons] targetPolygons = [Polygon(poly) for poly in tgtPolygons] polygonsToDelete = [] for sPoly in sourcePolygons: for tPoly in targetPolygons: if sPoly.isEqualToPolygon(tPoly): polygonsToDelete.append(tPoly.path) break if not len(polygonsToDelete): cmds.select(selectedNodes[1]) raise Exception("There is no same polygons in these 2 objects.") else: cmds.delete(polygonsToDelete) cmds.select(selectedNodes[1]) print("time consumed: " + str(time.clock() - start))
def shell_border_edges_to_hard(): """ Sets uv border edges on a mesh has hard, and everythign else as soft. """ objList = cmds.ls(sl=True, o=True) finalBorder = [] for subObj in objList: cmds.select(subObj, r=True) cmds.polyNormalPerVertex(ufn=True) cmds.polySoftEdge(subObj, a=180, ch=1) cmds.select(subObj + '.map[*]', r=True) polySelectBorderShell(borderOnly=True) uvBorder = cmds.polyListComponentConversion(te=True, internal=True) uvBorder = cmds.ls(uvBorder, fl=True) for curEdge in uvBorder: edgeUVs = cmds.polyListComponentConversion(curEdge, tuv=True) edgeUVs = cmds.ls(edgeUVs, fl=True) if len(edgeUVs) > 2: finalBorder.append(curEdge) cmds.polySoftEdge(finalBorder, a=0, ch=1) cmds.select(objList)
def makePlanar(components): """ This definition planarizes the given Components. :param components: Components to planarizes. ( List ) """ object = cmds.ls(components, o=True) if object: transform = getTransform(object) vertices = cmds.ls(cmds.polyListComponentConversion(components, toVertex=True), fl=True) barycenters = cmds.xform(vertices, q=True, t=True, ws=True) barycenter = getAverageVector([(barycenters[i], barycenters[i + 1], barycenters[i + 2]) for i in range(0, len(barycenters), 3)]) normals = [float(normal) for data in cmds.polyInfo(cmds.polyListComponentConversion(components, toFace=True), faceNormals=True) for normal in data.split()[2:5]] normals = [(normals[i], normals[i + 1], normals[i + 2]) for i in range(0, len(normals), 3)] averageNormal = vectorMatrixMultiplication(normalize(getAverageVector(normals)), cmds.xform(transform, query=True, matrix=True, worldSpace=True)) offset = -dot(averageNormal, barycenter) for vertex in vertices: position = cmds.xform(vertex, q=True, t=True, ws=True) distance = -(dot(averageNormal, position) + offset) cmds.xform(vertex, r=True, t=(averageNormal[0] * distance, averageNormal[1] * distance, averageNormal[2] * distance))
def edgeLoopWeights(edgeList): """ """ # Check Edge List if not edgeList: raise Exception('Invalid or empty edge list!') edgeList = cmds.filterExpand(edgeList, ex=True, sm=32) or [] if not edgeList: raise Exception('Invalid edge list! List of polygon edges required...') # Get Mesh from Edges mesh = list(set(cmds.ls(edgeList, o=True) or [])) if len(mesh) > 1: raise Exception('Edges from multiple mesh shapes were supplied! ' + str(mesh)) mesh = mesh[0] for edge in edgeList: # Get Edge ID edgeID = glTools.utils.component.index(edge) # Get Vertices from Edge edgeVerts = cmds.polyListComponentConversion(edge, fe=True, tv=True) # Get Average Vertex Weights cmds.select(edgeVerts) glTools.tools.copyPasteWeights.averageWeights() # Select Edge Loop Vertices cmds.polySelect(mesh, edgeLoop=edgeID) loopEdges = cmds.ls(sl=1, fl=1) loopVerts = cmds.polyListComponentConversion(loopEdges, fe=True, tv=True) cmds.select(loopVerts) glTools.tools.copyPasteWeights.pasteWeights() # Return Result return mesh
def getUVBoarder(self): sl = cmds.ls(selection=True, flatten=True) a = cmds.polyListComponentConversion( sl[0] ,fromFace=1, toUV=1) cmds.select(a) mel.eval("polySelectBorderShell 0;") sl = cmds.ls(selection=True, flatten=True) b = cmds.polyListComponentConversion( sl ,fromUV=1, toFace=1) cmds.select(b)
def vertNeighbors(vert, vertLoop): #find the verticles connected to this vertex by edges connectedEdges = cmds.polyListComponentConversion(vert, toEdge=True) connectedVerts = cmds.polyListComponentConversion(connectedEdges, toVertex = True) #select the connected verticles, then deselect the verticles on the loop cmds.select(connectedVerts, replace = True) cmds.select(vertLoop, deselect = True)
def convertSelection(self, toType): if toType == 'face': return cmds.polyListComponentConversion( self.getSelection(), internal = True, toFace = True ) elif toType == 'edge': return cmds.polyListComponentConversion( self.getSelection(), internal = True, toEdge = True ) elif toType == 'edgeBorder': return cmds.polyListComponentConversion( self.getSelection(), internal = False, toEdge = True ) elif toType == 'vertex': return cmds.polyListComponentConversion( self.getSelection(), toVertex = True )
def findCorrespondingVertInLoop(vert, edgeLoop): ''' Finds a vert on the edgeLoop whose edge is shared with the given vert ''' nearestVerts = mc.ls(mc.polyListComponentConversion(mc.polyListComponentConversion(vert, fv=True, te=True), fe=True, tv=True), fl=True) for vert in nearestVerts: if vert in edgeLoop: return vert return None
def findScaleMatrix(point, allPoints, allPointPos, rotationMat): ''' Finds the change in local scale at a vertex by comparing the bounding boxes around the polygons sharing a vertex before and after transformation. This is used to scale the motion vectors for each vertex to account for differences in proportion between the source and target models Returns a 3x3 scale matrix point: Point to be examined allPoints: list of Maya vertex indices, e.g. 'sourceModel.vtx[0] allPointPos: list of positions of these vertices in world space rotationMat: rotation matrix describing transformation from source to deformed source vertex. Necessary to undo the rotation before bounding box calculation to ensure a correct ration ''' # find faces sharing a vertex faces = cmds.polyListComponentConversion( point, fv=True, tf=True ) faces = cmds.ls( faces, flatten=True ) vList = cmds.polyListComponentConversion( faces, ff=True, tv=True ) vList = cmds.ls( vList, flatten=True ) vertPos = [] for i in range(0, len(vList)): vertPos.append(cmds.pointPosition(vList[i], w=True)) #find bounding box of vertices BB = [] BB.append(getExtremePoint("x", False, vertPos)) BB.append(getExtremePoint("x", True, vertPos)) BB.append(getExtremePoint("y", False, vertPos)) BB.append(getExtremePoint("y", True, vertPos)) BB.append(getExtremePoint("z", False, vertPos)) BB.append(getExtremePoint("z", True, vertPos)) sizeBB = numpy.array([BB[1] - BB[0], BB[3] - BB[2], BB[5] - BB[4]]) vInd = [] # extracting the vertex indices in vList adjusted from http://stackoverflow.com/questions/10365225/extract-digits-in-a-simple-way-from-a-python-string # answer by user senderle for i in vList: temp = re.findall('\d+', i) vInd.append(int(temp[len(temp)-1])) vertPos2 = [] for i in vInd: vertPos2.append(numpy.asarray(rotationMat[i] * numpy.transpose(allPointPos[i]))) #find bounding box of deformed vertices BB2 = [] BB2.append(float(getExtremePoint("x", False, vertPos2))) BB2.append(float(getExtremePoint("x", True, vertPos2))) BB2.append(float(getExtremePoint("y", False, vertPos2))) BB2.append(float(getExtremePoint("y", True, vertPos2))) BB2.append(float(getExtremePoint("z", False, vertPos2))) BB2.append(float(getExtremePoint("z", True, vertPos2))) sizeBB2 = numpy.array([BB2[1] - BB2[0], BB2[3] - BB2[2], BB2[5] - BB2[4]]) s = sizeBB2/sizeBB S = numpy.matrix([[s[0],0,0],[0,s[1],0],[0,0,s[2]]]) return S
def getNextEdge( edge, baseEdges, orderedEdges=[] ): faces = cmds.polyListComponentConversion( edge, tf=1 ) targetEdges = cmds.polyListComponentConversion( faces, te=1 ) for targetEdge in cmds.ls( targetEdges, fl=1 ): if targetEdge in orderedEdges: continue if not targetEdge in baseEdges: continue if targetEdge == edge: continue return targetEdge return None
def getAdjacentFaces(self, mesh, face): # select face cmds.select(mesh + ".f[" + str(face) + "]", r=True) # convert to edges, to faces cmds.select(cmds.polyListComponentConversion(ff=True, te=True)) cmds.select(cmds.polyListComponentConversion(fe=True, tf=True, border=True)) adjacentFaces = cmds.ls(sl=True, fl=True) # deselect cmds.select(d=True) return adjacentFaces
def getNeighboringEdgeloops(edgeLoop): ''' Get the neighboring edge loop. Takes in and returns verts, not edges ''' expandedVerts = mc.ls(mc.polyListComponentConversion(mc.polyListComponentConversion(edgeLoop, fv=True, te=True), fe=True, tv=True), fl=True) expandedEdgeVerts = mc.ls(edgeLoop, fl=True) for vert in expandedEdgeVerts: if vert in expandedVerts: expandedVerts.remove(vert) return mc.ls(expandedVerts, fl=True)
def snapComponentsOnClosestVertex(referenceObject, components, tolerance) : """ This function snaps vertices onto the reference object vertices. :param referenceObject: Reference mesh. :type referenceObject: str :param components: Components. :type components: list """ vertices = cmds.ls(cmds.polyListComponentConversion(components, toVertex=True), fl=True) progressBar = mel.eval("$container=$gMainProgressBar"); cmds.progressBar(progressBar, edit=True, beginProgress=True, isInterruptable=True, status="Snapping vertices ...", maxValue=len(vertices)) loadPlugin("nearestPointOnMesh") nearestPointOnMeshNode = mel.eval("nearestPointOnMesh " + referenceObject) for vertex in vertices : if cmds.progressBar(progressBar, query=True, isCancelled=True) : break closestDistance = MAXIMUM_SEARCH_DISTANCE vertexPosition = cmds.pointPosition(vertex, world=True) cmds.setAttr(nearestPointOnMeshNode + ".inPosition", vertexPosition[0], vertexPosition[1], vertexPosition[2]) associatedFaceId = cmds.getAttr(nearestPointOnMeshNode + ".nearestFaceIndex") vtxsFaces = cmds.filterExpand(cmds.polyListComponentConversion((referenceObject + ".f[" + str(associatedFaceId) + "]"), fromFace=True, toVertexFace=True), sm=70, expand=True) closestPosition = [] for vtxsFace in vtxsFaces : associatedVtx = cmds.polyListComponentConversion(vtxsFace, fromVertexFace=True, toVertex=True) associatedVtxPosition = cmds.pointPosition(associatedVtx, world=True) distance = norme(vertexPosition, associatedVtxPosition) if distance < closestDistance : closestDistance = distance closestPosition = associatedVtxPosition if closestDistance < tolerance : cmds.move(closestPosition[0], closestPosition[1], closestPosition[2], vertex, worldSpace=True) cmds.progressBar(progressBar, edit=True, step=1) cmds.progressBar(progressBar, edit=True, endProgress=True) cmds.delete(nearestPointOnMeshNode)
def getWindingOrder( facepath, doUvs=True ): '''will return the uvs or verts of a face in their proper 'winding order'. this can be used to determine things like uv face normals and... well, pretty much that''' toReturn = [] vtxFaces = cmd.ls(cmd.polyListComponentConversion(facepath,toVertexFace=True),flatten=True) for vtxFace in vtxFaces: if doUvs: uvs = cmd.polyListComponentConversion(vtxFace,fromVertexFace=True,toUV=True) toReturn.append( uvs[0] ) else: vtx = cmd.polyListComponentConversion(vtxFace,fromVertexFace=True,toVertex=True) toReturn.append( vtx[0] ) return toReturn
def smartNormals(reverse=0): '''Changes the vertex normals on a edge by edge basis to that of the larger faces vertex normals''' #We start a new undo chunk to capture all the work cmds.undoInfo( ock=1 ) try: sel = selection() edgeLengthList = getEdgeLengths(sel.selection.keys()) for key in sorted(edgeLengthList, reverse=1): key = key[-1] #Find the dag node name to be used in the polyNormalPerVertex command dagName = key.split('.')[0] cmds.select(dagName) vertices = cmds.ls(cmds.polyListComponentConversion(key,tv=1),fl=1) #Get the edges faces and check to make sure it finds two otherwise skip it because its a boarder edge faces = cmds.ls(cmds.polyListComponentConversion(key,tf=1),fl=1) if len(faces) == 2 : #Get the area of the two faces to compare their size face1Num = int(faces[0].split('[')[-1].split(']')[0]) area1 = getFaceArea(face1Num) face2Num = int(faces[1].split('[')[-1].split(']')[0]) area2 = getFaceArea(face2Num) if area1 > area2 : if reverse: largerFace , smallerFace = face2Num , face1Num else: largerFace , smallerFace = face1Num , face2Num else: if reverse: largerFace , smallerFace = face1Num , face2Num else: largerFace , smallerFace = face2Num , face1Num print "larger face - " + str(largerFace) + " || smaller face - " + str(smallerFace) #For the two verts attached to the edge set the smaller faces vertex normals to the cooresponding larger faces vertex normals #This command is run on the vertex per face so that we can set each one independantly #EXAMPLE: We run it on pCube1.vtxFace [0] [1] which only sets the vertex 0 attached to face 1 #instead of all the faces vertex 0 is attached to if we used pCube1.vtx[0] as the compoenent for vert in vertices : vertNum = int(vert.split('[')[-1].split(']')[0]) #Get the larger faces cooresponding vertex normal normal = cmds.polyNormalPerVertex((dagName + '.vtxFace[' + str(vertNum) + '][' + str(largerFace) + ']'),q=1,xyz=1) #Set the smaller faces cooresponding vertex normal cmds.polyNormalPerVertex((dagName + '.vtxFace[' + str(vertNum) + '][' + str(smallerFace) + ']'),xyz=normal) print "cmds.polyNormalPerVertex((" + dagName + '.vtxFace[' + str(vertNum) + '][' + str(smallerFace) + ']),xyz=' + str(normal) + ')' sel.restoreSelection() except Exception, e: traceback.print_exc()
def convertEdgesToVerts (edges): if not edges: return [] verts = cmds.polyListComponentConversion(edges, fromEdge=True, toVertex=True) return cmds.ls(verts, flatten=True)
def __init__(self): self.objDic = {} self.matDic = {} iniSel = mc.ls(sl=True) self.polySel = mc.polyListComponentConversion(iniSel, fe=True, fv=True, fuv=True, ff=True, tf=True) # construct obj dictioanry # review: iterators fastest with api for fce in self.polySel: obj, face = fce.split('.') sFaces = None sFaces = self.objDic.get(obj) if sFaces is None: self.objDic[obj] = [fce] else: sFaces.append(fce) self.objDic[obj] = sFaces # construct mat dictionary for objM in self.objDic: grpIds = mc.ls(mc.listHistory(objM), type='groupId') shGrps = [] # only one material object if 0 == len(grpIds): lsShape = mc.listRelatives(objM, s=True) shGrps = [ mc.listConnections(lsShape, c=True, type='shadingEngine')[1] ] # objects with more than one material else: shGrps = mc.listConnections(grpIds, type='shadingEngine') # polySelection initial flatten polySelFl = mc.ls(self.polySel, fl=True) # for material for shGrp in shGrps: material = mc.listConnections(shGrp + '.surfaceShader', c=True)[1] facesMat = [] # only one material object if 0 == len(grpIds): pNum = mc.polyEvaluate(f=True) facesMat = mc.ls((objM + '.f[0:' + str(pNum - 1) + ']'), fl=True) # objects with more than one material else: mc.select(clear=True) mc.hyperShade(objects=material) facesMat = mc.ls(sl=True, fl=True) mc.select(clear=True) # compare faces in initial selection for fce in facesMat: if fce in polySelFl: sFaces = None sFaces = self.matDic.get(material) if sFaces == None: self.matDic[material] = [fce] else: sFaces.append(fce) self.matDic[material] = sFaces # remove flatten lists in dictionaries mc.select(self.matDic[material], r=True) flatenFaces = mc.ls(sl=True) self.matDic[material] = flatenFaces
def saveWeights(geos, filepath=None, mode=kAPPEND): reportUsageToAuthor() start = time.clock() miscData = api.writeExportDict(TOOL_NAME, TOOL_VERSION) #if filepath is None, then generate a default filepath based on the location of the file if filepath is None: filepath = getDefaultPath() else: filepath = Path(filepath) geoAndData = {} skinPercent = cmd.skinPercent xform = cmd.xform #define teh data we're gathering joints = {} jointHierarchies = {} weightData = [] #does the weight file already exist? if so, load it up and append data if append mode is true if filepath.exists and mode == kAPPEND: tmpA, joints, jointHierarchies, weightData = filepath.unpickle() #data gathering time! for geo in geos: geoNode = geo verts = cmd.ls(cmd.polyListComponentConversion(geo, toVertex=True), fl=True) skinClusters = cmd.ls(cmd.listHistory(geo), type='skinCluster') if len(skinClusters) > 1: api.melWarning("more than one skinCluster found on %s" % geo) continue try: skinCluster = skinClusters[0] except IndexError: msg = "cannot find a skinCluster for %s" % geo api.melWarning(msg) #raise SkinWeightException(msg) for idx, vert in enumerate(verts): jointList = skinPercent(skinCluster, vert, ib=1e-4, q=True, transform=None) weightList = skinPercent(skinCluster, vert, ib=1e-4, q=True, value=True) if jointList is None: raise SkinWeightException( "I can't find any joints - sorry. do you have any post skin cluster history???" ) #so this is kinda dumb - but using a dict here we can easily remap on restore if joint names #are different by storing the dict's value as the joint to use, and the key as the joint that #the vert was originally weighted to for j in jointList: joints[j] = j pos = xform(vert, q=True, ws=True, t=True) vertData = VertSkinWeight(pos) vertData.populate(geo, idx, jointList, weightList) weightData.append(vertData) #lastly, add an attribute to the object describing where the weight file exists dirOfCurFile = Path(cmd.file(q=True, sn=True)).up() if geoNode.find('.') != -1: geoNode = geo.split('.')[0] if not cmd.objExists('%s.weightSaveFile' % geoNode): cmd.addAttr(geoNode, ln='weightSaveFile', dt='string') relToCur = filepath.relativeTo(dirOfCurFile) if relToCur is None: relToCur = filepath cmd.setAttr('%s.weightSaveFile' % geoNode, relToCur.asfile(), type='string') #sort the weightData by ascending x values so we can search faster weightData = sortByIdx(weightData) #generate joint hierarchy data - so if joints are missing on load we can find the best match for j in joints.keys(): jointHierarchies[j] = getAllParents(j) toWrite = miscData, joints, jointHierarchies, weightData filepath = Path(filepath) filepath.pickle(toWrite, False) melPrint('Weights Successfully %s to %s: time taken %.02f seconds' % ('Saved' if mode == kREPLACE else 'Appended', filepath.resolve(), time.clock() - start)) return filepath
def copy(): polygons = m.ls(m.polyListComponentConversion(tf=True), fl=True, l=True) if polygons: m.polyClipboard(polygons[0], copy=True, shader=True, uv=True, color=True)
def _move_shell(shell, move_uv): cmds.select(cmds.polyListComponentConversion(shell, tuv=True)) cmds.polyEditUV(u=move_uv.u, v=move_uv.v) cmds.select(clear=True)
'%s.normalCamera' % shader) # 将bump输出给材质球 mc.connectAttr('%s.outColor' % nodeColor, '%s.color' % shader) # 将图片输出给材质球 # 模型部分 obj = myFolder + folder + '/' + mc.getFileList( folder=myFolder + folder, filespec='*.obj')[0] # 获取模型文件 mc.file(obj, i=True, ns='wang%02d' % i) # 导入模型 geometry = mc.ls(geometry=True) # 选择模型 mc.select(geometry[0]) print geometry mc.hyperShade(a=shader, assign=True) # 赋予材质 mc.select(mc.listRelatives(mc.ls(geometry=True), p=True, path=True), r=True) nodes = mc.ls(sl=True) edges = mc.ls(mc.polyListComponentConversion(te=True), fl=True) a = [] b = [] for edge in edges: mc.select(edge) uvs = mc.ls(mc.polyListComponentConversion(tuv=True), fl=True) for uv in uvs: p = mc.polyEditUV(uv, query=True) a.append(p) if len(a) == 4: if a[0] == a[1] and a[2] == a[3]: b.append(edge) elif a[0] == a[2] and a[1] == a[3]: b.append(edge) elif a[0] == a[3] and a[1] == a[2]:
def uv_from_element(element): """Return the UV coordinate of given 'element' Supports components, meshes, nurbs. """ supported = ["mesh", "nurbsSurface"] uv = [0.5, 0.5] if "." not in element: type = cmds.nodeType(element) if type == "transform": geometry_shape = cmds.listRelatives(element, shapes=True) if len(geometry_shape) >= 1: geometry_shape = geometry_shape[0] else: return elif type in supported: geometry_shape = element else: cmds.error("Could not do what you wanted..") return else: # If it is indeed a component - get the current Mesh try: parent = element.split(".", 1)[0] # Maya is funny in that when the transform of the shape # of the component elemen has children, the name returned # by that elementection is the shape. Otherwise, it is # the transform. So lets see what type we're dealing with here. if cmds.nodeType(parent) in supported: geometry_shape = parent else: geometry_shape = cmds.listRelatives(parent, shapes=1)[0] if not geometry_shape: cmds.error("Skipping %s: Could not find shape." % element) return if len(cmds.ls(geometry_shape)) > 1: cmds.warning("Multiple shapes with identical " "names found. This might not work") except TypeError as e: cmds.warning("Skipping %s: Didn't find a shape " "for component elementection. %s" % (element, e)) return try: type = cmds.nodeType(geometry_shape) if type == "nurbsSurface": # If a surfacePoint is elementected on a nurbs surface root, u, v = element.rsplit("[", 2) uv = [float(u[:-1]), float(v[:-1])] if type == "mesh": # ----------- # Average the U and V values # =========== uvs = cmds.polyListComponentConversion(element, toUV=1) if not uvs: cmds.warning("Couldn't derive any UV's from " "component, reverting to default U and V") raise TypeError # Flatten list of Uv's as sometimes it returns # neighbors like this [2:3] instead of [2], [3] flattened = [] for uv in uvs: flattened.extend(cmds.ls(uv, flatten=True)) uvs = flattened sumU = 0 sumV = 0 for uv in uvs: try: u, v = cmds.polyEditUV(uv, query=True) except: cmds.warning("Couldn't find any UV coordinated, " "reverting to default U and V") raise TypeError sumU += u sumV += v averagedU = sumU / len(uvs) averagedV = sumV / len(uvs) uv = [averagedU, averagedV] except TypeError: pass return uv
def loadWeights(objects, filepath=None, usePosition=True, tolerance=TOL, axisMult=None, swapParity=True, averageVerts=True, doPreview=False, meshNameRemapDict=None, jointNameRemapDict=None): ''' loads weights back on to a model given a file ''' #nothing to do... if not objects: print 'No objects given...' return if filepath is None: filepath = getDefaultPath() if not filepath.exists(): print 'File does not exist %s' % filepath return start = time.clock() #setup the mappings VertSkinWeight.MESH_NAME_REMAP_DICT = meshNameRemapDict VertSkinWeight.JOINT_NAME_REMAP_DICT = jointNameRemapDict #cache heavily access method objects as locals... skinPercent = cmd.skinPercent progressWindow = cmd.progressWindow xform = cmd.xform #now get a list of all weight files that are listed on the given objects - and #then load them one by one and apply them to the appropriate objects objItemsDict = {} for obj in objects: items = [] #this holds the vert list passed in IF any if obj.find('.') != -1: items = [obj] obj = obj.split('.')[0] try: objItemsDict[obj].extend(items) except KeyError: objItemsDict[obj] = items numItems = len(objItemsDict) curItem = 1 progressWindow(e=True, title='loading weights from file %d items' % numItems) #load the data from the file miscData, joints, jointHierarchies, weightData = Path(filepath).unpickle() #build the search tree tree = BinarySearchTree(weightData) findMethod = tree.getWithin findMethodKw = {'tolerance': tolerance} if averageVerts: findMethod = tree.getWithinRatio findMethodKw = {'ratio': tolerance} #remap joint names in the saved file to joint names that are in the scene - they may be namespace differences... missingJoints = set() for n, j in joints.iteritems(): if not cmd.objExists(j): #see if the joint with the same leaf name exists in the scene idxA = j.rfind(':') idxB = j.rfind('|') idx = max(idxA, idxB) if idx != -1: leafName = j[idx + 1:] if objExists(leafName): joints[n] = leafName else: search = cmd.ls('%s*' % leafName, r=True, type='joint') if search: joints[n] = search[0] print '%s remapped to %s' % (j, search[0]) #now that we've remapped joint names, we go through the joints again and remap missing joints to their nearest parent #joint in the scene - NOTE: this needs to be done after the name remap so that parent joint names have also been remapped for n, j in joints.iteritems(): if not cmd.objExists(j): dealtWith = False for jp in jointHierarchies[n]: if cmd.objExists(jp): joints[n] = jp dealtWith = True break if dealtWith: print '%s remapped to %s' % (j, jp) continue missingJoints.add(n) #now remove them from the list [joints.pop(n) for n in missingJoints] #axisMults can be used to alter the positions of verts saved in the weightData array - this is mainly useful for applying #weights to a mirrored version of a mesh - so weights can be stored on meshA, meshA duplicated to meshB, and then the #saved weights can be applied to meshB by specifying an axisMult=(-1,1,1) OR axisMult=(-1,) if axisMult is not None: for data in weightData: for n, mult in enumerate(axisMult): data[n] *= mult #we need to re-sort the weightData as the multiplication could have potentially reversed things... i could probably #be a bit smarter about when to re-order, but its not a huge hit... so, meh weightData = sorted(weightData) #using axisMult for mirroring also often means you want to swap parity tokens on joint names - if so, do that now. #parity needs to be swapped in both joints and jointHierarchies if swapParity: for joint, target in joints.iteritems(): joints[joint] = str(names.Name(target).swap_parity()) for joint, parents in jointHierarchies.iteritems(): jointHierarchies[joint] = [ str(names.Name(p).swap_parity()) for p in parents ] for geo, items in objItemsDict.iteritems(): #if the geo is None, then check for data in the verts arg - the user may just want weights #loaded on a specific list of verts - we can get the geo name from those verts skinCluster = '' verts = cmd.ls(cmd.polyListComponentConversion(items if items else geo, toVertex=True), fl=True) #do we have a skinCluster on the geo already? if not, build one skinCluster = cmd.ls(cmd.listHistory(geo), type='skinCluster') if not skinCluster: skinCluster = cmd.skinCluster(geo, joints.values())[0] verts = cmd.ls(cmd.polyListComponentConversion(geo, toVertex=True), fl=True) else: skinCluster = skinCluster[0] #if we're using position, the restore weights path is quite different vertJointWeightData = [] if usePosition: progressWindow(e=True, status='searching by position: %s (%d/%d)' % (geo, curItem, numItems), maxValue=len(verts)) vCount = -1 for vert in verts: vCount += 1 pos = Vector(xform(vert, q=True, ws=True, t=True)) foundVerts = findMethod(pos, **findMethodKw) #accumulate found verts jointWeightDict = {} for v in foundVerts: for joint, weight in zip(v.joints, v.weights): actualJoint = joints[joint] weight += jointWeightDict.get(actualJoint, 0) jointWeightDict[actualJoint] = weight #normalize the weights weightSum = float(sum(jointWeightDict.values())) if weightSum != 1: for joint, weight in jointWeightDict.iteritems(): jointWeightDict[joint] = weight / weightSum #append the data vertJointWeightData.append((vert, jointWeightDict.items())) #deal with the progress window - this isn't done EVERY vert because its kinda slow... if vCount % 50 == 0: progressWindow(e=True, progress=vCount) #bail if we've been asked to cancel if progressWindow(q=True, isCancelled=True): progressWindow(ep=True) return progressWindow(e=True, status='maya is setting skin weights...') setSkinWeights(skinCluster, vertJointWeightData) #otherwise simply restore by id else: progressWindow(e=True, status='searching by vert name: %s (%d/%d)' % (geo, curItem, numItems), maxValue=len(verts)) #rearrange the weightData structure so its ordered by vertex name weightDataById = {} [ weightDataById.setdefault(i.getVertName(), (i.joints, i.weights)) for i in weightData ] for vert in verts: #progressWindow(edit=True, progress=cur / num * 100.0) #if progressWindow(q=True, isCancelled=True): #progressWindow(ep=True) #return #cur += 1 try: jointList, weightList = weightDataById[vert] except KeyError: #in this case, the vert doesn't exist in teh file... print '### no point found for %s' % vert continue else: jointList = [joints[j] for j in jointList] jointsAndWeights = zip(jointList, weightList) skinPercent(skinCluster, vert, tv=jointsAndWeights) #remove unused influences from the skin cluster cmd.skinCluster(skinCluster, edit=True, removeUnusedInfluence=True) curItem += 1 end = time.clock() print 'time for weight load %.02f secs' % (end - start)
def getUVData(meshName, joinName, borderEdges): uvCount = cmds.polyEvaluate(meshName, uv=True) uvCoordDict = {} for i in range(0, uvCount): uvCoord = cmds.polyEditUV("%s.map[%s]" % (meshName, i), q=True) uvCoordDict.update({i: uvCoord}) triangleVertexDict = {} faceCount = cmds.polyEvaluate(meshName, f=True) for i in range(0, faceCount): toVertex = cmds.polyListComponentConversion( "%s.f[%s]" % (meshName, i), tv=True, ) cmds.select(toVertex) faceRefVertex = cmds.ls(sl=True, fl=True) triangleVertexDict.update({i: faceRefVertex}) cmds.select(cl=True) edgeCount = cmds.polyEvaluate(meshName, e=True) border = cmds.polyListComponentConversion(cmds.ls(sl=True, fl=True), uvs=True) cmds.select(cl=True) uvCoordListForSpine = [] for i in uvCoordDict.keys(): # print i uvCoordListForSpine.append(uvCoordDict[i][0]) uvCoordListForSpine.append(uvCoordDict[i][1]) # print "uvCoordListForSpine",uvCoordListForSpine trianglesListForSpine = [] for i in triangleVertexDict.keys(): trianglesListForSpine.append( int(triangleVertexDict[i][0].split("[")[1].split("]")[0])) trianglesListForSpine.append( int(triangleVertexDict[i][1].split("[")[1].split("]")[0])) trianglesListForSpine.append( int(triangleVertexDict[i][2].split("[")[1].split("]")[0])) # print "trianglesListForSpine",trianglesListForSpine allvertexs = cmds.polyListComponentConversion(meshName, tv=True) #vertexList = [] cmds.select(allvertexs) vertexList = cmds.ls(sl=True, fl=True) cmds.select(cl=True) ox = cmds.getAttr("%s.translateX" % joinName) oy = cmds.getAttr("%s.translateY" % joinName) print ox, oy # print vertexList vertexPositionForSpine = [] for i in vertexList: # print cmds.pointPosition(i) vertexPositionForSpine.append(cmds.pointPosition(i)[0] - ox) vertexPositionForSpine.append(cmds.pointPosition(i)[1] - oy) # print "vertexPositionForSpin",vertexPositionForSpine # borderEdgesString = cmds.getAttr("%s.borderList"%meshName) # borderEdges = borderEdgesString.split(",") borderEdgesCount = len(borderEdges) edgesVertexDict = {} for i in range(0, borderEdgesCount): toVertex = cmds.polyListComponentConversion( borderEdges[i], tv=True, ) cmds.select(toVertex) edgeRefVertex = cmds.ls(sl=True, fl=True) edgesVertexDict.update({i: edgeRefVertex}) edgesVertexForSpineList = [] for i in edgesVertexDict.keys(): v1 = edgesVertexDict[i][0].split("[")[-1].split("]")[0] v2 = edgesVertexDict[i][1].split("[")[-1].split("]")[0] edgesVertexForSpineList.append(int(v1) * 2) edgesVertexForSpineList.append(int(v2) * 2) #print "edgesVertexForSpineList",edgesVertexForSpineList width = cmds.getAttr("%s.scaleX" % meshName) height = cmds.getAttr("%s.scaleZ" % meshName) dataForSpine = { "type": "mesh", "width": width, "height": height, "uvs": uvCoordListForSpine, "triangles": trianglesListForSpine, "vertices": vertexPositionForSpine, "hull": borderEdgesCount, "edges": edgesVertexForSpineList } return dataForSpine
def clampVertInfluenceCount(geos=None): ''' ''' global kMAX_INF_PER_VERT, kMIN_SKIN_WEIGHT_VALUE progressWindow = cmd.progressWindow skinPercent = cmd.skinPercent halfMin = kMIN_SKIN_WEIGHT_VALUE / 2.0 if geos is None: geos = cmd.ls(sl=True) for geo in geos: skin = cmd.ls(cmd.listHistory(geo), type='skinCluster')[0] verts = cmd.ls(cmd.polyListComponentConversion(geo, toVertex=True), fl=True) inc = 100.0 / len(verts) progress = 0 vertsFixed = [] for vert in verts: progress += inc progressWindow(e=True, progress=progress) reapplyWeights = False weightList = skinPercent(skin, vert, ib=1e-5, q=True, value=True) if len(weightList) > kMAX_INF_PER_VERT: jointList = skinPercent(skin, vert, ib=halfMin, q=True, transform=None) sorted = zip(weightList, jointList) sorted.sort() #now clamp to the highest kMAX_INF_PER_VERT number of weights, and re-normalize sorted = sorted[-kMAX_INF_PER_VERT:] weightSum = sum([a for a, b in sorted]) t_values = [(b, a / weightSum) for a, b in sorted] reapplyWeights = True else: for n, v in enumerate(weightList): if v <= kMIN_SKIN_WEIGHT_VALUE: jointList = skinPercent(skin, vert, ib=halfMin, q=True, transform=None) t_values = [(a, b) for a, b in zip(jointList, weightList) if b > halfMin] reapplyWeights = True break if reapplyWeights: js = [a for a, b in t_values] vs = renormalizeWithMinimumValue([b for a, b in t_values]) t_values = zip(js, vs) skinPercent(skin, vert, tv=t_values) vertsFixed.append(vert) #turn on limiting in the skinCluster cmd.setAttr('%s.maxInfluences' % skin, kMAX_INF_PER_VERT) cmd.setAttr('%s.maintainMaxInfluences' % skin, 1) print 'fixed skin weights on %d verts' % len(vertsFixed)
def findVertsInVolume(meshes, volume): ''' returns a dict containing meshes and the list of vert attributes contained within the given <volume> ''' #define a super simple vector class to additionally record vert id with position... class VertPos(Vector): def __init__(self, x, y, z, vertIdx=None): Vector.__init__(self, [x, y, z]) self.id = vertIdx #this dict provides the functions used to determine whether a point is inside a volume or not insideDeterminationMethod = { ExportManager.kVOLUME_SPHERE: isPointInSphere, ExportManager.kVOLUME_CUBE: isPointInCube } #if there are any uniform overrides for the contained method (called if the volume's scale is #unity) it can be registered here insideDeterminationIfUniform = { ExportManager.kVOLUME_SPHERE: isPointInUniformSphere, ExportManager.kVOLUME_CUBE: isPointInCube } #grab any data we're interested in for the volume volumePos = Vector(cmd.xform(volume, q=True, ws=True, rp=True)) volumeScale = map(abs, cmd.getAttr('%s.s' % volume)[0]) volumeBasis = rigUtils.getObjectBasisVectors(volume) #make sure the basis is normalized volumeBasis = [v.normalize() for v in volumeBasis] #now lets determine the volume type type = ExportManager.kVOLUME_SPHERE try: type = int(cmd.getAttr('%s.exportVolume' % volume)) except TypeError: pass isContainedMethod = insideDeterminationMethod[type] print 'method for interior volume determination', isContainedMethod.__name__ sx = volumeScale[0] if Vector(volumeScale).within((sx, sx, sx)): try: isContainedMethod = insideDeterminationIfUniform[type] except KeyError: pass #now lets iterate over the geometry meshVertsWithin = {} for mesh in meshes: #its possible to pass not a mesh but a component in - this is totally valid, as the polyListComponentConversion #should make sure we're always dealing with verts no matter what, but we still need to make sure the dict key is #the actual name of the mesh - hence this bit of jiggery pokery dotIdx = mesh.rfind('.') meshName = mesh if dotIdx == -1 else mesh[:dotIdx] meshPositions = [] meshVertsWithin[meshName] = meshPositions #this gives us a huge list of floats - each sequential triple is the position of a vert try: #if this complains its most likely coz the geo is bad - so skip it... vertPosList = cmd.xform(cmd.ls(cmd.polyListComponentConversion( mesh, toVertex=True), fl=True), q=True, t=True, ws=True) except TypeError: continue count = len(vertPosList) / 3 for idx in xrange(count): pos = VertPos(vertPosList.pop(0), vertPosList.pop(0), vertPosList.pop(0), idx) contained = isContainedMethod(pos, volumePos, volumeScale, volumeBasis) if contained: pos.weight = contained[1] meshPositions.append(pos) return meshVertsWithin
def solidifyObject(object, height=1, divisions=2, history=True): """ Solidifies given object. :param object: Object. :type object: str :param height: Extrusion height. :type height: float :param division: Extrusion divisions. :type division: float :param history: Keep construction history. :type history: bool """ if hasBorderEdges(object): transform = getTransform(object) vertices = cmds.ls(cmds.polyListComponentConversion(object, toVertex=True), fl=True) barycenters = cmds.xform(vertices, q=True, t=True, ws=True) barycenter = getAverageVector([(barycenters[i], barycenters[i + 1], barycenters[i + 2]) for i in range(0, len(barycenters), 3)]) normals = cmds.polyNormalPerVertex(cmds.polyListComponentConversion( object, toVertexFace=True), q=True, xyz=True) normals = [(normals[i], normals[i + 1], normals[i + 2]) for i in range(0, len(normals), 3)] averageNormal = vectorMatrixMultiplication( normalize(getAverageVector(normals)), cmds.xform(transform, query=True, matrix=True, worldSpace=True)) facesCount = cmds.polyEvaluate(object, face=True) faces = object + ".f[0:" + str(facesCount - 1) + "]" extrude = cmds.polyExtrudeFacet(faces, constructionHistory=1, keepFacesTogether=1, divisions=divisions) cmds.setAttr(extrude[0] + ".localTranslateZ", height) borderEdges = cmds.polyListComponentConversion(faces, te=True, bo=True) cmds.polyMapCut(borderEdges) uvs = cmds.polyListComponentConversion(object + ".f[0:" + str(facesCount - 1) + "]", toUV=1) cmds.polyEditUV(uvs, u=0, v=-5) extendedFaces = cmds.ls(faces, fl=True) for i in range(divisions): adjacentEdges = cmds.polyListComponentConversion(extendedFaces, ff=True, te=True) extendedFaces.extend( cmds.ls(cmds.polyListComponentConversion(adjacentEdges, fe=True, tf=True), fl=True)) borderFaces = list( set(extendedFaces).difference(set(cmds.ls(faces, fl=True)))) cmds.select(borderFaces) cmds.polyAutoProjection(borderFaces, t=barycenter, ry=getAngle((0, 0, 1), averageNormal), rz=getAngle((1, 0, 0), averageNormal)) uvs = cmds.polyListComponentConversion(borderFaces, toUV=1) cmds.polyEditUV(uvs, u=0, v=-5) not history and cmds.delete(object, ch=True)
def loadWeights(objects, filepath=None, usePosition=True, tolerance=TOL, axisMult=None, swapParity=True, averageVerts=True, doPreview=False, meshNameRemapDict=None, jointNameRemapDict=None): ''' loads weights back on to a model given a file. NOTE: the tolerance is an axis tolerance NOT a distance tolerance. ie each axis must fall within the value of the given vector to be considered a match - this makes matching a heap faster because vectors can be culled from the a sorted list. possibly implementing some sort of oct-tree class might speed up the matching more, but... the majority of weight loading time at this stage is spent by maya actually applying skin weights, not the positional searching ''' reportUsageToAuthor() start = time.clock() #setup the mappings VertSkinWeight.MESH_NAME_REMAP_DICT = meshNameRemapDict VertSkinWeight.JOINT_NAME_REMAP_DICT = jointNameRemapDict #cache heavily access method objects as locals... skinPercent = cmd.skinPercent progressWindow = cmd.progressWindow xform = cmd.xform #now get a list of all weight files that are listed on the given objects - and #then load them one by one and apply them to the appropriate objects filesAndGeos = {} dirOfCurFile = Path(cmd.file(q=True, sn=True)).up() for obj in objects: items = [] #this holds the vert list passed in IF any if obj.find('.') != -1: items = [obj] obj = obj.split('.')[0] try: file = Path(dirOfCurFile + cmd.getAttr('%s.weightSaveFile' % obj) if filepath is None else filepath) if file.exists and not file.isfile(): raise TypeError() except TypeError: #in this case, no weightSave file existed on the object, so try using the default file if it exists file = getDefaultPath() if filepath is None else filepath if not file.exists: api.melError('cant find a weightSaveFile for %s - skipping' % obj) continue filesAndGeos.setdefault(file, {}) try: filesAndGeos[file][obj].extend(items) except KeyError: filesAndGeos[file][obj] = items print filesAndGeos unfoundVerts = [] for filepath, objItemsDict in filesAndGeos.iteritems(): numItems = len(objItemsDict) curItem = 1 progressWindow(e=True, title='loading weights from file %d items' % numItems) miscData, joints, jointHierarchies, weightData = Path( filepath).unpickle() if miscData[api.kEXPORT_DICT_TOOL_VER] != TOOL_VERSION: api.melWarning( "WARNING: the file being loaded was stored from an older version (%d) of the tool - please re-generate the file. Current version is %d." % (miscData[api.kEXPORT_DICT_TOOL_VER], TOOL_VERSION)) for geo, items in objItemsDict.iteritems(): #the miscData contains a dictionary with a bunch of data stored from when the weights was saved - do some #sanity checking to make sure we're not loading weights from some completely different source curFile = cmd.file(q=True, sn=True) origFile = miscData['scene'] if curFile != origFile: api.melWarning( 'the file these weights were saved in a different file from the current: "%s"' % origFile) #response = cmd.confirmDialog(t='files differ...', m='the file these weights were saved from was %s\nthis is different from your currently opened file.\n\nis that OK?' % origFile, b=('Proceed', 'Cancel'), db='Proceed') #if response == 'Cancel': return #axisMults can be used to alter the positions of verts saved in the weightData array - this is mainly useful for applying #weights to a mirrored version of a mesh - so weights can be stored on meshA, meshA duplicated to meshB, and then the #saved weights can be applied to meshB by specifying an axisMult=(-1,1,1) OR axisMult=(-1,) if axisMult is not None: for data in weightData: for n, mult in enumerate(axisMult): data[n] *= mult #we need to re-sort the weightData as the multiplication could have potentially reversed things... i could probably #be a bit smarter about when to re-order, but its not a huge hit... so, meh weightData = sortByIdx(weightData) #using axisMult for mirroring also often means you want to swap parity tokens on joint names - if so, do that now. #parity needs to be swapped in both joints and jointHierarchies if swapParity: for joint, target in joints.iteritems(): joints[joint] = str(names.Name(target).swap_parity()) for joint, parents in jointHierarchies.iteritems(): jointHierarchies[joint] = [ str(names.Name(p).swap_parity()) for p in parents ] #if the geo is None, then check for data in the verts arg - the user may just want weights #loaded on a specific list of verts - we can get the geo name from those verts skinCluster = '' verts = cmd.ls(cmd.polyListComponentConversion( items if items else geo, toVertex=True), fl=True) #remap joint names in the saved file to joint names that are in the scene - they may be namespace differences... missingJoints = set() for j in joints.keys(): if not cmd.objExists(j): #see if the joint with the same leaf name exists in the scene idxA = j.rfind(':') idxB = j.rfind('|') idx = max(idxA, idxB) if idx != -1: leafName = j[idx:] search = cmd.ls('%s*' % leafName, r=True, type='joint') if len(search): joints[j] = search[0] #now that we've remapped joint names, we go through the joints again and remap missing joints to their nearest parent #joint in the scene - NOTE: this needs to be done after the name remap so that parent joint names have also been remapped for j, jRemap in joints.iteritems(): if not cmd.objExists(jRemap): dealtWith = False for n, jp in enumerate(jointHierarchies[j]): #if n > 2: break remappedJp = jp if jp in joints: remappedJp = joints[jp] if cmd.objExists(remappedJp): joints[j] = remappedJp dealtWith = True break if dealtWith: continue missingJoints.add(j) #now remove them from the list [joints.pop(j) for j in missingJoints] for key, value in joints.iteritems(): if key != value: print '%s remapped to %s' % (key, value) #do we have a skinCluster on the geo already? if not, build one skinCluster = cmd.ls(cmd.listHistory(geo), type='skinCluster') if not skinCluster: skinCluster = cmd.skinCluster(geo, joints.values())[0] verts = cmd.ls(cmd.polyListComponentConversion(geo, toVertex=True), fl=True) else: skinCluster = skinCluster[0] num = len(verts) cur = 0.0 inc = 100.0 / num findMethod = findBestVector if averageVerts: findMethod = getDistanceWeightedVector #if we're using position, the restore weights path is quite different if usePosition: progressWindow(edit=True, status='searching by position: %s (%d/%d)' % (geo, curItem, numItems)) queue = api.CmdQueue() print "starting first iteration with", len(weightData), "verts" iterationCount = 1 while True: unfoundVerts = [] foundVerts = [] for vert in verts: progressWindow(edit=True, progress=cur) cur += inc pos = Vector(xform(vert, q=True, ws=True, t=True)) vertData = findMethod(pos, weightData, tolerance, doPreview) try: #unpack data to locals try: jointList, weightList = vertData.joints, vertData.weights except AttributeError: raise NoVertFound try: #re-map joints to their actual values actualJointNames = [ joints[j] for j in jointList ] #check sizes - if joints have been remapped, there may be two entries for a joint #in the re-mapped jointList - in this case, we need to re-gather weights actualJointsAsSet = set(actualJointNames) if len(actualJointsAsSet) != len( actualJointNames): #so if the set sizes are different, then at least one of the joints is listed twice, #so we need to gather up its weights into a single value new = {} [ new.setdefault(j, 0) for j in actualJointNames ] #init the dict with 0 values for j, w in zip(actualJointNames, weightList): new[j] += w #if the weightList is empty after renormalizing, nothing to do - keep loopin actualJointNames, weightList = new.keys( ), new.values() if not weightList: raise NoVertFound except KeyError: #if there was a key error, then one of the joints was removed from the joints dict #as it wasn't found in the scene - so get the missing joints, remove them from the #list and renormalize the remaining weights jointListSet = set(jointList) diff = missingJoints.difference(jointListSet) weightList = renormalizeWeights( jointList, weightList, diff) actualJointNames = [ joints[j] for j in jointList ] #if the weightList is empty after renormalizing, nothing to do - keep loopin if not weightList: raise NoVertFound #normalize the weightlist weightList = normalizeWeightList(weightList) #zip the joint names and their corresponding weight values together (as thats how maya #accepts the data) and fire off the skinPercent cmd jointsAndWeights = zip(actualJointNames, weightList) queue.append( 'skinPercent -tv %s %s %s' % (' -tv '.join([ '%s %s' % t for t in jointsAndWeights ]), skinCluster, vert)) foundVertData = VertSkinWeight(pos) foundVertData.populate(vertData.mesh, vertData.idx, actualJointNames, weightList) foundVerts.append(foundVertData) except NoVertFound: unfoundVerts.append(vert) #print '### no point found for %s' % vert #so with the unfound verts - sort them, call them "verts" and iterate over them with the newly grown weight data #the idea here is that when a vert is found its added to the weight data (in memory not on disk). by performing #another iteration for the previously un-found verts, we should be able to get a better approximation verts = unfoundVerts if unfoundVerts: if foundVerts: weightData = sortByIdx(foundVerts) else: print "### still unfound verts, but no new matches were made in previous iteration - giving up. %d iterations performed" % iterationCount break else: print "### all verts matched! %d iterations performed" % iterationCount break iterationCount += 1 print "starting iteration %d - using" % iterationCount, len( weightData), "verts" #for www in weightData: print www #bail if we've been asked to cancel if progressWindow(q=True, isCancelled=True): progressWindow(ep=True) return progressWindow(e=True, status='maya is setting skin weights...') queue() #otherwise simply restore by id else: progressWindow(edit=True, status='searching by vert name: %s (%d/%d)' % (geo, curItem, numItems)) queue = api.CmdQueue() #rearrange the weightData structure so its ordered by vertex name weightDataById = {} [ weightDataById.setdefault(i.getVertName(), (i.joints, i.weights)) for i in weightData ] for vert in verts: progressWindow(edit=True, progress=cur / num * 100.0) if progressWindow(q=True, isCancelled=True): progressWindow(ep=True) return cur += 1 try: jointList, weightList = weightDataById[vert] except KeyError: #in this case, the vert doesn't exist in teh file... print '### no point found for %s' % vert continue else: jointsAndWeights = zip(jointList, weightList) skinPercent(skinCluster, vert, tv=jointsAndWeights) #remove unused influences from the skin cluster cmd.skinCluster(skinCluster, edit=True, removeUnusedInfluence=True) curItem += 1 if unfoundVerts: cmd.select(unfoundVerts) end = time.clock() api.melPrint('time for weight load %.02f secs' % (end - start))
def Event_ItemsCount_3(self): self.window.Text_Items.moveCursor(QTextCursor.End) self.window.Text_Items.insertPlainText('\n'.join(maya_cmds.polyListComponentConversion(toFace=True)) + '\n')
def getUV(*args): """takes a selection of one or two verts and returns one UV position. If just the surface is selected, it will return UV vals of (.5, .5)""" #get vertex sel = cmds.ls(sl=True) #------filter for vertices (or cvs?) vertices = cmds.filterExpand(sm=(31), fp=True, ex=True) try: if len(vertices)>2: cmds.warning("You've selected more than two verts. Two is the max number I can take") except: cmds.warning("Please select one or two vertices!") uvs = [] if vertices: #here deal with option to use one or average uv values of two selections (shouldn't be more than two)? for vert in vertices: #convert vertex to uvs thisUV = cmds.polyListComponentConversion(vert, fv=True, tuv=True)[0] uvs.append(thisUV) else: cmds.warning("You haven't selected any verts! Select one or two to place a follicle") #convert vertices to uvs and get their value if uvs: uvList = [] for uv in uvs: #grab first (cuz verts can be multiple uv's) thisUV = cmds.ls(uv)[0] #convert the uv index to u and v values uvVal = cmds.polyEditUV(uv, q=True) uvList.append(uvVal) U = [] V = [] sizeUV = len(uvList) #print uvList for uv in uvList: U.append(uv[0]) V.append(uv[1]) #print "U = %s"%U #print "V = %s"%V #DO THE AVERAGING HERE x = 0 y = 0 for a in U: x = x + a for b in V: y = y + b u = x/sizeUV v = y/sizeUV uvVal = [u,v] cmds.select(vertices) shapeName = vertices[0].rpartition(".vtx")[0] meshName = cmds.listRelatives(shapeName, p=True)[0] folName = cmds.textFieldGrp(widgets["nameTFG"], q=True, tx=True) uValue = uvVal[0] vValue = uvVal[1] follicle(meshName, folName, uValue, vValue) else: pass
def saveWeights(geos, filepath=None): start = time.clock() miscData = {} #if filepath is None, then generate a default filepath based on the location of the file if filepath is None: filepath = getDefaultPath() else: filepath = Path(filepath) geoAndData = {} skinPercent = cmd.skinPercent xform = cmd.xform #define teh data we're gathering masterJointList = [] weightData = [] #data gathering time! rigidBindObjects = [] for geo in geos: skinClusters = cmd.ls(cmd.listHistory(geo), type='skinCluster') if len(skinClusters) > 1: printWarningStr("more than one skinCluster found on %s" % geo) continue #so the geo isn't skinned in the traditional way - check to see if it is parented to a joint. if so, #stuff it into the rigid bind list to be dealt with outside this loop, and continue if not skinClusters: dealtWith = False for p in iterParents(geo): if cmd.nodeType(p) == 'joint': rigidBindObjects.append((geo, p)) masterJointList.append(p) masterJointList = removeDupes(masterJointList) dealtWith = True break if not dealtWith: msg = "cannot find a skinCluster for %s" % geo printWarningStr(msg) continue skinCluster = skinClusters[0] masterJointList += cmd.skinCluster(skinCluster, q=True, inf=True) masterJointList = removeDupes(masterJointList) verts = cmd.ls(cmd.polyListComponentConversion(geo, toVertex=True), fl=True) for idx, vert in enumerate(verts): jointList = skinPercent(skinCluster, vert, ib=1e-4, q=True, transform=None) weightList = skinPercent(skinCluster, vert, ib=1e-4, q=True, value=True) if jointList is None: raise SkinWeightException( "I can't find any joints - sorry. do you have any post skin cluster history???" ) pos = xform(vert, q=True, ws=True, t=True) vertData = VertSkinWeight(pos) vertData.populate(geo, idx, [masterJointList.index(j) for j in jointList], weightList) weightData.append(vertData) #deal with rigid bind objects for geo, j in rigidBindObjects: verts = cmd.ls(cmd.polyListComponentConversion(geo, toVertex=True), fl=True) for idx, vert in enumerate(verts): jIdx = masterJointList.index(j) pos = xform(vert, q=True, ws=True, t=True) vertData = VertSkinWeight(pos) vertData.populate(geo, idx, [jIdx], [1]) weightData.append(vertData) #sort the weightData by ascending x values so we can search faster weightData.sort() #turn the masterJointList into a dict keyed by index joints = {} for n, j in enumerate(masterJointList): joints[n] = j #generate joint hierarchy data - so if joints are missing on load we can find the best match jointHierarchies = {} for n, j in joints.iteritems(): jointHierarchies[n] = getAllParents(j) toWrite = miscData, joints, jointHierarchies, weightData filepath = Path(filepath) filepath.pickle(toWrite) print 'Weights Successfully Saved to %s: time taken %.02f seconds' % ( filepath, time.clock() - start) return filepath
cmds.setAttr(mulDiv + ".input2", -1, -1, -1) objects = cmds.ls(sl=True) if '.vtx' in objects[0]: #*********** Get parent name ****************** ObjectParent = cmds.listRelatives(objects[1], p=True) #*********** Get object position ****************** position = cmds.xform(objects[0], q=True, ws=True, t=True) #******* Create a group driven by pointOnPolyContraint ********** groupName = cmds.group(em=True, name=("grp_ptc_" + objects[1])) cmds.parent(groupName, ObjectParent[0]) #******* Get the UV map relationed with the vtx ********** mapList = cmds.polyListComponentConversion(objects[0], fv=- True, tuv=True) #******* Create a pointOnPolyContraint ********** contraintNames = cmds.pointOnPolyConstraint(objects[0], groupName, mo=False, o=[0, 0, 0], w=1) #************* Disconnect rotation chanel **************************************** mel.eval("CBdeleteConnection " + groupName + ".rotateX;") mel.eval("CBdeleteConnection " + groupName + ".rotateY;") mel.eval("CBdeleteConnection " + groupName + ".rotateZ;") #******* Get U and V values from map array ********** uvvalues = cmds.polyEditUV(mapList, q=True) contraintAttr = cmds.listAttr(contraintNames[0], k=True) #******* Assign the U and V values respectively from maplist ********** cmds.setAttr((contraintNames[0] + "." + contraintAttr[10]), uvvalues[0])
def __publish_maya_shader_network(self, item, output, work_template, primary_publish_path, sg_task, comment, thumbnail_path, progress_cb): """ Publish shader networks for the asset and register with Shotgun. :param item: The item to publish :param output: The output definition to publish with :param work_template: The work template for the current scene :param primary_publish_path: The path to the primary published file :param sg_task: The Shotgun task we are publishing for :param comment: The publish comment/description :param thumbnail_path: The path to the publish thumbnail :param progress_cb: A callback that can be used to report progress """ # determine the publish info to use # progress_cb(10, "Determining publish details") # get the current scene path and extract fields from it # using the work template: scene_path = os.path.abspath(cmds.file(query=True, sn=True)) fields = work_template.get_fields(scene_path) publish_version = fields["version"] tank_type = output["tank_type"] obj_name = item['name'] fields['obj_name'] = obj_name fields['name'] = re.sub(r'[\W_]+', '', obj_name) # create the publish path by applying the fields # with the publish template: publish_template = output["publish_template"] publish_path = publish_template.apply_fields(fields) # ensure the publish folder exists: publish_folder = os.path.dirname(publish_path) self.parent.ensure_folder_exists(publish_folder) # determine the publish name: publish_name = fields.get("obj_name") if not publish_name: publish_name = os.path.basename(publish_path) # Find additional info from the scene: # progress_cb(10, "Analysing scene") # clean up any hookup nodes that existed before _clean_shader_hookup_script_nodes() # there's probably a better way to do this. i am jon snow (i know # nothing) shading_groups = set() shad_group_to_obj = {} if cmds.ls(obj_name, dag=True, type="mesh"): faces = cmds.polyListComponentConversion(obj_name, toFace=True) for shading_group in cmds.listSets(type=1, object=faces[0]): shading_groups.add(shading_group) shad_group_to_obj[shading_group] = obj_name shaders = set() script_nodes = [] for shading_group in list(shading_groups): connections = cmds.listConnections( shading_group, source=True, destination=False) for shader in cmds.ls(connections, materials=True): shaders.add(shader) obj_name = shad_group_to_obj[shading_group] # can't seem to store arbitrary data in maya in any # reasonable way. would love to know a better way to # do this. for now, just create a script node that # we can easily find and deduce an object name and # shader name. Yes, this is hacky. script_node = cmds.scriptNode( name="SHADER_HOOKUP_" + obj_name, scriptType=0, # execute on demand. beforeScript=shader, ) script_nodes.append(script_node) if not shaders: progress_cb(100, "No shader networks to export.") return select_nodes = list(shaders) #select_nodes.extend(list(shading_groups)) select_nodes.extend(script_nodes) cmds.select(select_nodes, replace=True) # write a .ma file to the publish path with the shader network definitions progress_cb(25, "Exporting the shader network.") cmds.file( publish_path, type='mayaAscii', exportSelected=True, options="v=0", prompt=False, force=True ) # clean up shader hookup nodes. they should exist in the publish file # only. _clean_shader_hookup_script_nodes() # register the publish: progress_cb(75, "Registering the publish") args = { "tk": self.parent.tank, "context": self.parent.context, "comment": comment, "path": publish_path, "name": publish_name, "version_number": publish_version, "thumbnail_path": thumbnail_path, "task": sg_task, "dependency_paths": [primary_publish_path], "published_file_type":tank_type } tank.util.register_publish(**args)
def align(self, nodes=None, axis='x', mode='mid', *args): # Default nodes to selection if not provided if nodes == None: nodes = cmds.ls(sl=True) elif not nodes: cmds.confirmDialog(t='Error', m='Nothing is selected', b='Ok') _nodes = [] for node in nodes: if '.f[' in node: node = cmds.polyListComponentConversion(node, fromFace=True, toVertex=True) elif '.e[' in node: node = cmds.polyListComponentConversion(node, fromEdge=True, toVertex=True) cmds.select(node) node = cmds.ls(sl=True, fl=True) _nodes.extend(node) node = _nodes minMode = mode == 'min' maxMode = mode == 'max' midMode = mode == 'mid' # Get the dimensions of our objects if axis == 'x': start = 0 elif axis == 'y': start = 1 elif axis == 'z': start = 2 else: cmds.confirmDialog(t='error', m='Unknown Axis', b='Ok') bboxes = {} values = [] for node in nodes: if '.vtx[' in node: ws = cmds.xfrom(node, q=True, t=True, w=True) minValue = midValue = maxValue = ws[start] else: bbox = cmds.exactWorldBoundingBox(node) minValue = bbox[start] maxValue = bbox[start + 3] midValue = (minValue + maxValue) / 2 bboxes[node] = (minValue, midValue, maxValue) if minMode: values.append(minValue) elif maxMode: values.append(maxValue) else: values.append(midValue) # Calculating the alignment point if minMode: target = min(values) elif maxMode: target = max(values) else: target = sum(values) / len(values) # Figure out the distance to the alignment point for node in nodes: bbox = bboxes[node] minValue, midValue, maxValue = bbox ws = cmds.xform(node, q=True, t=True, ws=True) width = maxValue - minValue if minMode: distance = minValue - target ws[start] = (minValue - distance) + width / 2 elif maxMode: distance = target - maxValue ws[start] = (maxValue + distance) - width / 2 else: distance = target - midValue ws[start] = midValue + distance # Move objects to the target cmds.xform(node, translation=ws, ws=True)
def move_center2selection(): if not cmds.ls(sl=True): return if cmds.selectMode( q=True, co=True ): selection = cmds.ls(sl=True) selMode='component' verticies = cmds.polyListComponentConversion(selection , tv=True) verticies = cmds.filterExpand(verticies, sm=31) center = [0, 0, 0] for i in range(3): center[i] = sum([cmds.pointPosition(vtx, w=True)[i] for vtx in verticies])/len(verticies) elif cmds.selectMode( q=True, o=True ): selMode='object' #スムース直後だとうまくオブジェクト選択にならないときがあるのでいったんコンポーネントを経由 cmds.selectMode(co=True) cmds.selectMode(o=True) selection = cmds.ls(sl=True, l=True, tr=True) childeNodes = common.search_polygon_mesh(selection, serchChildeNode=True, fullPath=True) selection = list(set(selection + childeNodes)) preLock = {} for sel in selection: preLock[sel] = cmds.getAttr(sel+'.translateX', lock=True) for ax in ['X','Y','Z']: cmds.setAttr(sel+'.translate'+ax, lock=False) if selMode == 'object': #正しいバウンディングボックスを得るために複製、ベイク、取得、削除する duplicate_mesh = cmds.duplicate(selection, rc=True)#子の名前を固有にしてエラー回避rc=True cmds.bakePartialHistory(duplicate_mesh, ppt=True) bBox = cmds.exactWorldBoundingBox(duplicate_mesh, ignoreInvisible=False) center = [(bBox[i]+bBox[i+3])/2 for i in range(3)] cmds.delete(duplicate_mesh) for sel in selection: if np_flag: sel_pos = np.array(cmds.xform(sel, q=True, t=True, ws=True)) offset = sel_pos - np.array(center) else: sel_pos = cmds.xform(sel, q=True, t=True, ws=True) offset = [p-c for p, c in zip(sel_pos, center)] dummy = common.TemporaryReparent().main(mode='create')#モジュールでダミーの親作成 common.TemporaryReparent().main(sel, dummyParent=dummy, mode='cut') cmds.xform(sel, t=center, ws=True) verticies = cmds.polyListComponentConversion(sel, tv=True) verticies = cmds.filterExpand(verticies, sm=31) cmds.xform(verticies, t=offset, r=True, ws=True) cmds.xform(sel+'.scalePivot', t=center, ws=True) cmds.xform(sel+'.rotatePivot', t=center, ws=True) if preLock[sel]: for ax in ['X','Y','Z']: cmds.setAttr(sel+'.translate'+ax, lock=True) common.TemporaryReparent().main(sel, dummyParent=dummy, mode='parent') common.TemporaryReparent().main(sel, dummyParent=dummy, mode='delete') freeze.main(mesh=selection) cmds.select(selection, r=True)
noSurfaceShader=True, empty=True, name=shading_grp_surface) else: if not cmds.objectType(shading_grp_surface) == "shadingEngine": while (cmds.objExists(shading_grp_surface)): shading_grp_surface = "{0}1".format(shading_grp_surface) shading_grp_surface = cmds.sets(renderable=True, noSurfaceShader=True, empty=True, name=shading_grp_surface) faces_idx0 = cmds.polyListComponentConversion( ["{}.vtx[{}]".format(objs[0], i) for i in idx0], fromVertex=1, toFace=1, internal=1) faces_idx1 = cmds.polyListComponentConversion( ["{}.vtx[{}]".format(objs[1], i) for i in idx1], fromVertex=1, toFace=1, internal=1) cmds.sets(faces_idx0, fe=shading_grp_surface) cmds.sets(faces_idx1, fe=shading_grp_surface) if not cmds.objExists(shading_grp_saddle): shading_grp_saddle = cmds.sets(renderable=True, noSurfaceShader=True, empty=True, name=shading_grp_saddle)
def fuv2e(_list): return mc.polyListComponentConversion(_list, fuv=True, te=True)
def splitMeshByInfluences(threshold, *args): import maya.mel as mel finalMeshList = [] # find the meshes that the user has selected selected = cmds.ls(sl=True, type="transform") # Create an empty set. We wil add to it later. cmds.select(cl=True) setName = cmds.sets(n="Rigid_Meshes") rigidMeshMasterGrp = cmds.group(em=True, name="Rigid_Mesh") # for each mesh: for mesh in selected: rigidMeshMeshGrp = cmds.group(em=True, name="Rigid_" + mesh, p=rigidMeshMasterGrp) #print "Mesh:"+mesh skinCluster = mel.eval('findRelatedSkinCluster %s' % mesh) influences = cmds.skinCluster(skinCluster, q=True, inf=True) #print influences for inf in influences: # Duplicate the mesh with input connections dupeMesh = cmds.duplicate(mesh, name=mesh + "__" + inf, rr=False)[0] #print "DupeMesh: "+dupeMesh for attr in [ "tx", "ty", "tz", "rx", "ry", "rz", "sx", "sy", "sz", "v" ]: cmds.setAttr(dupeMesh + "." + attr, lock=False, k=True) cmds.makeIdentity(dupeMesh, t=1, r=1, s=1, apply=True) cmds.select(dupeMesh, r=True) mel.eval("CenterPivot") cmds.parent(dupeMesh, rigidMeshMeshGrp) finalMeshList.append(dupeMesh) cmds.sets(dupeMesh, add=setName) # Select the verts that are influenced by the inf joint. if len(influences) <= 1: const = cmds.parentConstraint(inf, rigidMeshMeshGrp, dupeMesh, mo=True)[0] cmds.setAttr(const + "." + rigidMeshMeshGrp + "W1", 0) else: verts = [] for x in range(cmds.polyEvaluate(mesh, v=True)): v = cmds.skinPercent(skinCluster, '%s.vtx[%d]' % (mesh, x), transform=inf, q=True) if v > threshold: verts.append('%s.vtx[%d]' % (dupeMesh, x)) #print verts if verts: cmds.select(verts) # Convert the selection to contained faces if len(verts) != cmds.polyEvaluate(mesh, v=True): mel.eval("InvertSelection;") cmds.select( cmds.polyListComponentConversion(fv=True, tf=True, internal=True)) cmds.delete() cmds.select(dupeMesh, r=True) mel.eval("CenterPivot") const = cmds.parentConstraint(inf, rigidMeshMeshGrp, dupeMesh, mo=True)[0] cmds.setAttr(const + "." + rigidMeshMeshGrp + "W1", 0) else: print "No Valid Verts so we didnt use this influence." cmds.delete(dupeMesh) cmds.select(rigidMeshMasterGrp, hi=True) cmds.createDisplayLayer(cmds.ls(sl=True), name="RigidMesh_L") return finalMeshList
#This script allows u to reverse the result of smooth operation in maya after deleting the history #It also preserves the original UV of the mesh #Select the mesh u want to unsmooth and execute the script #Script might take some time to execute depending on the polycount... import maya.cmds as cmds import maya.mel as mel #Get the selected mesh selectedMesh=cmds.ls( selection=True )[0] #Get the vertex count i.e. vertex id of last vertex... vertexCount=cmds.polyEvaluate( v=True ) vertexId = selectedMesh+'.vtx['+str(vertexCount)+']' cmds.select(vertexId) #Convert selection to edges... x=cmds.polyListComponentConversion( fv=True,te=True ) cmds.select(x) #get the edges number... k=x[0].rfind(']') l=x[0].rfind('[') start = x[0][l+1:] edges = str(start[:-1]) colon = edges.split(':') #Select edge loops and rings... mel.eval('SelectEdgeLoopSp;') mel.eval('polySelectEdgesEveryN "edgeRing" 2;') mel.eval('SelectEdgeLoopSp;') mel.eval('SelectEdgeLoopSp;') mel.eval('SelectEdgeLoopSp;')
def cleanupNonManifoldGeometry(self, normals = True): ## Get all the mesh that has mentalraySubdivApprox connected and has non-manifold problem # subdiv_mesh = [cmds.listRelatives(mesh, parent = True, fullPath = True)[0] for mesh in cmds.ls(type = 'mesh') if cmds.listConnections(mesh, type = 'mentalraySubdivApprox') if cmds.polyInfo(mesh, nme = True) or cmds.polyInfo(nmv = True)] subdiv_mesh = [cmds.listRelatives(mesh, parent = True, fullPath = True)[0] for mesh in cmds.ls(type = 'mesh') if cmds.polyInfo(mesh, nme = True) or cmds.polyInfo(nmv = True)] subdiv_mesh = list( set( subdiv_mesh ) ) if subdiv_mesh: for each in subdiv_mesh: ## Make sure we do indeed have nonmanifold geometry ## nonManifold = cmds.polyInfo(each, nmv = True, nme = True) if nonManifold: proceed = cmds.confirmDialog(title = 'Non-Manifold Geometry!', message = 'Geo Name:\n%s' % each, button = ['Cleanup!', 'Skip...'], defaultButton = 'Skip...', cancelButton = 'Skip...', dismissString = 'Skip...') if proceed == 'Cleanup!': ## Conform the geo and see if that gets rid of all the nonmanifold bits ## if normals: cmds.polyNormal('%s.f[*]' % each, normalMode = 2, constructionHistory = True) edges = cmds.polyInfo(each, nme = True) if cmds.polyInfo(each, nme = True) else [] vertices = [] if edges else cmds.polyInfo(each, nmv = True) lastEdges = [] lastVertices = [] while ( not self.arraysMatch(lastEdges, edges) or not self.arraysMatch(lastVertices, vertices) ) and ( edges or vertices ): ## Remember what was nonmanifold last time ## lastEdges = edges lastVertices = vertices ## Split any nonmanifold edges ## if edges: cmds.polySplitEdge(edges, constructionHistory = True) vertices = cmds.polyInfo(each, nmv = True) edges = [] ## Split any remaining nonmanifold vertices ## if vertices: cmds.polySplitVertex(vertices, constructionHistory = True) vertices = [] ## Now check to see if the object is still nonmanifold ## nonManifold = cmds.polyInfo(each, nmv = True, nme = True) if nonManifold: ## Chip off the faces ## nonManifoldFaces = cmds.polyListComponentConversion(nonManifold, toFace = True) cmds.polyChipOff(nonManifoldFaces, kft = 0, dup = 0, constructionHistory = True) ## And then check for nonmanifold bits again ## edges = cmds.polyInfo(each, nme = True) if not edges: vertices = cmds.polyInfo(each, nmv = True) ## Check to see if we failed to cleanup if edges or vertices: cmds.warning('Failed to cleanup non-manifold geometry of %s...' % each)
def Event_ItemsCount_1(self): self.window.Text_Items.setPlainText('\n'.join(maya_cmds.polyListComponentConversion(toFace=True)) + '\n')
# 各水平のUVをpivotとして、垂直に整列する horizentalUVList.remove(_pivot) for uv in horizentalUVList: if mc.progressWindow(query=True, isCancelled=True): return False PROGRESS_AMOUNT += 1 #progress = PROGRESS_AMOUNT / UVAmount mc.progressWindow(title="UVAlign", edit=True, progress=PROGRESS_AMOUNT) doAlign(uv, 0) return True #---------------------------------------------# # pivotの格納 pivot = mc.ls(selection=True) pivot = mc.polyListComponentConversion(pivot, tuv=True) # 最初の方向(上下左右) verticalDir = [[0, 1], [0, -1]] horizentalDir = [[1, 0], [-1, 0]] # UVShellに含めているUVを取得する uvList_Shell = flatten( mc.polyListComponentConversion(pivot, tuv=True, uvShell=True)) isDone = alignUV(pivot[0]) mc.progressWindow(title="UVAlign", endProgress=True) print isDone #mc.select(uvList_Shell) #print(uvList_Shell)
def convertVertsToEdges (verts): if not verts: return [] edges = cmds.polyListComponentConversion(verts, fromVertex=True, toEdge=True) return cmds.ls(edges, flatten=True)
def convertFacesToVerts (faces): if not faces: return [] verts = cmds.polyListComponentConversion(faces, fromFace=True, toVertex=True) return cmds.ls(verts, flatten=True)
def getUVInformation(self): allMeshList = cmds.ls(type='mesh') noUVMeshList = [] uvInformationList = [] oldMeshList = [] amount = 0 cmds.progressWindow(title='Get UV Information', progress=amount, status='Reading: %s/%s' % (0, len(allMeshList)), isInterruptable=True, minValue=0, maxValue=len(allMeshList)) for mesh in allMeshList: if not mesh in oldMeshList: #~ 检验模型是否已经检查过 meshFileP2dList = [] meshVtxUVList = [] """找到所有的file和p2d""" shadingEngine = cmds.listConnections(mesh, s=False, d=True, type='shadingEngine') if shadingEngine == None: continue p2dList = cmds.ls(cmds.listHistory(shadingEngine), type='place2dTexture') for p2d in p2dList: outputP2dAttr = cmds.listConnections(p2d, s=False, d=True) file = None for item in outputP2dAttr: if file == None and cmds.objectType(item, isType='file'): file = item break tmp = [file, p2d] meshFileP2dList.append(tmp) """获取模型的shadingEngine连接的所有模型信息""" allShaderMesh = [] allMeshTrans = cmds.listConnections(shadingEngine, s=True, d=False, type='mesh') for meshTrans in allMeshTrans: shaderMesh = cmds.listRelatives(meshTrans)[0] allShaderMesh.append(shaderMesh) """遍历这些模型对应的UV信息""" for shaderMesh in allShaderMesh: """进度条""" # Check if the dialog has been cancelled if cmds.progressWindow(query=True, isCancelled=True): break amount += 1 cmds.progressWindow(edit=True, progress=amount, status='Reading: %s/%s' % (amount, len(allMeshList))) oldMeshList.append(shaderMesh) vtxIndexList = cmds.getAttr(shaderMesh + '.vrts', multiIndices=True) for vtx in vtxIndexList: cmds.select(shaderMesh + '.vtx[%s]' % vtx) uvMap = cmds.polyListComponentConversion(fv=True, tuv=True) if uvMap != []: uvInfo = cmds.polyEditUV(uvMap, q=True) uValue = int(uvInfo[0]) vValue = int(uvInfo[1]) uvBlock = [uValue, vValue] if not uvBlock in meshVtxUVList: meshVtxUVList.append(uvBlock) else: noUVMeshList.append(shaderMesh) tmpMeshMap = { 'meshFileP2dList': meshFileP2dList, 'meshVtxUVList': meshVtxUVList } uvInformationList.append(tmpMeshMap) cmds.progressWindow(endProgress=1) return uvInformationList