def middle2(self, s): middleL = [] #use input field data to determine flat uv set flatUvSet = self.findFlatUvSet(s) #get tips of geo and split to top and bottom pairs pair1, pair2 = self.findTips(s, flatUvSet) #select edges going the length on the cards and list as vertices pm.polyUVSet(s, currentUVSet =1, uvSet=flatUvSet) side1Edge = pm.polySelect(s, ass = 1, shortestEdgePathUV = (pair1[0].getUVIndices(str(flatUvSet))[0], pair1[1].getUVIndices(str(flatUvSet))[0])) side1 = pm.ls(pm.polyListComponentConversion(side1Edge, fe =1, tv =1), fl = 1) if len(side1) > 2: side2Edge = pm.polySelect(s, ass = 1, shortestEdgePathUV = (pair2[0].getUVIndices(str(flatUvSet))[0], pair2[1].getUVIndices(str(flatUvSet))[0])) side2 = pm.ls(pm.polyListComponentConversion(side2Edge, fe =1, tv =1), fl = 1) #select bottom verts and walk(traverse) to the middle of the geo on both sides mid1 = pm.ls(self.traverse(start = pair1[0], listToWalk = side1, multiplyBy = 0.5 )) mid2 = pm.ls(self.traverse(start = pair2[0], listToWalk = side2, multiplyBy = 0.5 )) #select shortest path between the 2 middle points and add to the middleL list MidLine = pm.polySelect(s, ass = 1, shortestEdgePathUV = (mid1[0].getUVIndices(str(flatUvSet))[0], mid2[0].getUVIndices(str(flatUvSet))[0])) middleL.append(MidLine) pm.select(cl = 1) if len(side1) % 2 == 0: mid3 = pm.ls(self.traverse(start = pair1[-1], listToWalk = side1, multiplyBy = 0.5 )) mid4 = pm.ls(self.traverse(start = pair2[-1], listToWalk = side2, multiplyBy = 0.5 )) MidLine2 = pm.polySelect(s, ass = 1, shortestEdgePathUV = (mid3[0].getUVIndices(str(flatUvSet))[0], mid4[0].getUVIndices(str(flatUvSet))[0])) middleL.append(MidLine2) pm.select(cl = 1) return pm.ls( middleL, fl = True)
def setPosUv(vtxs,length,side,uvDistorted): startUv = pm.ls(pm.polyListComponentConversion(vtxs[0],fv=1,tuv=1),fl=1) if side == 'left': pm.polyEditUV(startUv,r=0,u=0,v=0) else: pm.polyEditUV(startUv,r=0,u=1,v=0) for i in range(1,len(vtxs)): vtx1Pos = pm.xform(vtxs[i-1],q=1,t=1,ws=1) vtx2Pos = pm.xform(vtxs[i],q=1,t=1,ws=1) vtx1PosVec = MVector(vtx1Pos[0],vtx1Pos[1],vtx1Pos[2]) vtx2PosVec = MVector(vtx2Pos[0],vtx2Pos[1],vtx2Pos[2]) dist = (vtx2PosVec - vtx1PosVec).length() factor=0.0 if uvDistorted: factor = dist / length else: factor = 1.0 / (len(vtxs) - 1) uv1 = pm.ls(pm.polyListComponentConversion(vtxs[i-1],fv=1,tuv=1),fl=1) uv2 = pm.ls(pm.polyListComponentConversion(vtxs[i],fv=1,tuv=1),fl=1) uv1Pos = pm.polyEditUV(uv1,q=1) uv2Pos = uv1Pos[1] + factor if side == 'left': pm.polyEditUV(uv2,r=0,u=0,v=uv2Pos) else: pm.polyEditUV(uv2,r=0,u=1,v=uv2Pos)
def tear_face(self): sel = pm.selected() movetool = pm.melGlobals['gMove'] if all(isinstance(i, pm.MeshFace) for i in sel): if len(sel) == 1: pm.polyMapCut(sel) sel = pm.polyListComponentConversion(sel, ff=True, tuv=True) pm.select(sel) else: sewSel = pm.polyListComponentConversion(ff=True, te=True, internal=True) pm.polyMapCut(sel) pm.polyMapSewMove(sewSel, nf=10, lps=0, ch=1) sel = pm.polyListComponentConversion(sel, ff=True, tuv=True) pm.select(sel) pm.setToolTo(movetool)
def rig_makeBlockGeoFromJoint(meshes, influence, *args): '''Takes in a list of meshes to cut pieces that are influenced by influence object (joint) Args: meshes (list(pm.nt.Transform)): meshes to cut up influence (pm.nt.Joint): figures out the faces influenced based on this one joint Returns: list (pm.nt.Transform): list of block geometries created for that influence/joint Usage: rig_makeBlockGeoFromJoint(pm.ls(sl=True), 'jointTest_JNT') ''' blockgeo=[] for mesh in meshes: skinCluster = rig_getConnectedSkinCluster(mesh) if pm.objExists(skinCluster): influences = skinCluster.getWeightedInfluence() if influence in influences: faces = rig_getSkinClusterInfluencedMostFace(mesh, skinCluster, influence) if faces: deleteFaces=[] dup = pm.duplicate(mesh, rr=True) allFaces = pm.ls(pm.polyListComponentConversion( mesh, tf=True), fl=True) deleteFaces = list( set(allFaces).difference(set(faces))) deleteFaces = [pm.PyNode(face.name().replace(mesh.getShape().name(), dup[0].getShape().name())) for face in deleteFaces] if deleteFaces: pm.delete(deleteFaces) dup[0].rename('%s_%s_CUTUP'%(mesh.name(),influence.replace('_JNT',''))) blockgeo.append(dup[0]) else: pm.delete(dup[0]) return blockgeo
def move_face_shell(faces, u=0, v=0): """ Move all uvs related to arg faces by u and v values """ udim = uv_udim_convert([u,v]) uvs = pm.polyListComponentConversion(faces, tuv=True) pm.polyEditUV(uvs, u=-(u-1), v=-(v-1)) pm.sets(faces, n=set_name%str(udim))
def aw_muscleShrinkWrap(source, meshes): '''Attaches muscle objects to the source then targets and makes them conform to its shape Args: source (pm.PyNode): source object to get shape from targets (pm.PyNode): target objects to conform Returns (pm.nt.CMuscleSystem): muscle object that is created Usage: aw_muscleShrinkWrap(pm.ls(sl=True)[0], pm.ls(sl=True)[1:]) ''' #convert target to muscle pm.select(source, r=True) eval('cMuscle_makeMuscle(0)') #apply muscle skin deformer to source pm.select(meshes, r=True) eval('cMuscle_makeMuscleSystem(1)') #connect the two systems pm.select([source,meshes], r=True) eval('cMuscle_connectToSystem()') #get the system: pm.select(meshes, r=True) systems = eval('cMuscle_getSelectedDeformers("cMuscleSystem")') for system in systems: system=pm.PyNode(system) deformeds = pm.deformer(system, q=True, geometry=True) #print 'setting weights for muscle system: %s'%system #print deformeds #system.shrinkWrap.set(1) system.enableSliding.set(1) for deformed in deformeds: deformedVerts = pm.polyListComponentConversion(deformed,tv=True)
def __init__(self, uvs=None): if not uvs: self.uvs = pm.ls(pm.polyListComponentConversion(tuv=True), fl=True) else: self.uvs = uvs self.shells = [] self.type = 'standard'
def getVertsFromSelection(cls, sel, *args, **kwargs): ''' retains current selection, returns vert list flattented ''' verts = pm.polyListComponentConversion(sel, tv=True) pm.select(verts, r=True) verts = pm.ls(sl=True, flatten=True) pm.select(sel, r=True) return verts
def sample_density(self, *args): sel = pm.ls(pm.polyListComponentConversion(pm.selected(), tf=True), fl=True) ratios = [] for i in sel: ratios.append(math.sqrt(i.getUVArea() / i.getArea())) ratio = (sum(ratios) / len(sel)) * self.opts.width.getValue() self.texelDensity.setValue(ratio)
def pivot(self): oldSel = pm.selected() self.transform() selected = pm.selected() pm.delete(selected, constructionHistory = 1) pm.select(clear = 1) for s in selected: #remove previous transformation data pm.makeIdentity(s, apply = 1) ###get root faces from root edges root = self.root(s) rootFaces = pm.ls(pm.polyListComponentConversion(root, fe =1, tf =1), fl = True) pm.select(cl = 1) #get list of vertices contained in the faces points = [] for face in rootFaces: point = face.getPoints() for p in point: if p not in points: points.append(p) #get average from point list and put it on the surface of the geo faceAvg = s.getClosestPoint(self.vecAvg(points)) #move pivots to face average pm.xform(s, piv = faceAvg[0], ws = 1) #move geo to origin to restore transformations pm.move( 0,0,0, s, rpr=1 ) pos = pm.xform( s, q=1, t=1 ) pm.makeIdentity(s, apply = 1 ) #build matrix out of normal and side vectors faceNormal = self.getFaceNormals(rootFaces) rootVerts = pm.ls(pm.polyListComponentConversion(root, fe =1, tv =1), fl = True) rotVertCoords = [x.getPosition(space = 'object') for x in rootVerts] avgBasePos = self.vecAvg(rotVertCoords) mat = self.matrix_from_normal ( faceNormal, avgBasePos) #rotate to align to scene axis pm.xform(s, matrix = mat.asMatrixInverse()) pm.makeIdentity(s, apply = 1) pm.xform(s, matrix = mat) pm.setAttr( '%s.t' % s, pos[0]*-1,pos[1]*-1,pos[2]*-1) if pm.polyEvaluate(s, f = True)<2: pm.xform( s, piv = ( avgBasePos ), ws = 0 ) pm.select(oldSel)
def prepSelection(sel): verts = pm.filterExpand(sel, selectionMask=31) if verts: pm.polySelectConstraint(pp=3, type=0x0001) verts = pm.ls(sl=True, fl=True) return verts edge = pm.filterExpand(sel, selectionMask=32) if edge: verts = pm.polyListComponentConversion(edge, fromEdge=True, toVertex=True) return verts
def _get_bounds(sel): if sel > 1 and isinstance(sel[0], pm.Component): transform = sel[0].node().getTransform() t = pm.polyEvaluate(bc=True) bb = pm.dt.BoundingBox(pm.dt.Point(t[0][0], t[1][0], t[2][0]), pm.dt.Point(t[0][1], t[1][1], t[2][1])) verts = [i.getPosition() for i in pm.ls(pm.polyListComponentConversion(sel, tv=True), fl=True)] center = sum(verts) / len(verts) else: transform = sel[0] bb = sel[0].getBoundingBox() center = pm.objectCenter(sel[0]) return bb, center, transform
def UVFix(self): oldSel = pm.ls(sl = 1) selected = pm.ls(sl = 1, o = 1) pm.select(cl = 1) for s in selected: #############get info from other nodes myCurrentUvSet = pm.polyUVSet(s, q = True , currentUVSet = True )[0] pair1, pair2 = self.findTips(s, myCurrentUvSet) ###############select and store roots and tips tipsUV = [] rootEdges = pm.ls( pm.polySelect( s, ass = 1 ,shortestEdgePath = (pair2[0].index(), pair2[1].index() ) ), fl = 1) tipsUV.append( pm.ls( pm.polyListComponentConversion( rootEdges, fe =1, tuv =1), fl = True ) ) tipEdges = pm.ls( pm.polySelect( s, ass = 1 ,shortestEdgePath = (pair1[0].index(), pair1[1].index() ) ), fl = 1) tipsUV.append( pm.ls( pm.polyListComponentConversion( tipEdges, fe =1, tuv =1), fl = True ) ) #########select and unfold the middle part of the mesh pm.select( pm.ls(tipsUV, fl = 1), replace = True ) pm.runtime.InvertSelection() if self.squareCheckBox.getValue() == 1: pm.unfold(ps=0, us=False, i=4312, gmb=0.9457, pub=0, oa=1, ss=15.5797, gb=0.7597) ###########selecting length boarders side1 = pm.ls(pm.polySelect(ebp = [ tipEdges[0].index(), rootEdges[0].index()], ass = True ), fl = 1) side1 = [n for n in side1 if n not in rootEdges and n not in tipEdges] side2 = pm.ls(pm.polySelect(ebp = [ tipEdges[-1].index(), rootEdges[-1].index()], ass = True ), fl = 1) side2 = [n for n in side2 if n not in rootEdges and n not in tipEdges] ##########calculate all the averages boarder1Avg = self.tupleAvg([pair1[0].getUV(uvSet = myCurrentUvSet), pair2[0].getUV(uvSet = myCurrentUvSet)]) boarder2Avg = self.tupleAvg([pair1[1].getUV(uvSet = myCurrentUvSet), pair2[1].getUV(uvSet = myCurrentUvSet)]) islandAvg = self.tupleAvg([boarder1Avg, boarder2Avg]) #########straighten length boarders for x in side1: pm.polyEditUV(x, u = boarder1Avg[0], r = False, uvSetName = myCurrentUvSet) for x in side2: pm.polyEditUV(x, u = boarder2Avg[0], r = False, uvSetName = myCurrentUvSet) ##########get the perimeter of the uv island borderUVs = ['{}.map[{}]'.format(s,x.getUVIndices()[0]) for x in pm.ls(s.vtx, fl = 1) if x.isOnBoundary()] pm.select(borderUVs) pm.runtime.InvertSelection() pm.Unfold3D(pm.selected(),rs=2, ite=0, bi=1, p=0, u=1, ms=1024, tf=1) else: pm.Unfold3D(pm.selected(),rs=2, ite=0, bi=1, p=0, u=1, ms=1024, tf=1) pm.select(oldSel)
def getSymMap(mesh_node, uv_set="map1", num_split=10): # Check node mfn_mesh = getApiNode(mesh_node, OpenMaya.MFn.kMesh) mesh_node = NodeUtils.checkShapeNode(mesh_node) # Get All UVs u_values = OpenMaya.MFloatArray() v_values = OpenMaya.MFloatArray() mfn_mesh.getUVs(u_values, v_values, uv_set) # Push datas to Grid uv_grid = Grid(num_split) uv_grid.push_to_grid(u_values, v_values) # Get sym map sym_map = {} uv_grid.reset() while uv_grid.next_brick(): brick = uv_grid.split[uv_grid.idx] sym_brick = uv_grid.split[uv_grid.sym_idx] for b in brick: idx = pmc.polyListComponentConversion(mesh_node.map[int(b.keys()[0])], fromUV=True, toVertex=True) a = pmc.datatypes.Vector(1 - b.values()[0][0], b.values()[0][1], 0.0) tmp_length = None for sb in sym_brick: b = pmc.datatypes.Vector(sb.values()[0][0], sb.values()[0][1], 0.0) length = a.distanceTo(b) if tmp_length is None or length < tmp_length: tmp_length = length sym_idx = pmc.polyListComponentConversion(mesh_node.map[int(sb.keys()[0])], fromUV=True, toVertex=True) sym_map[pmc.PyNode(idx[0]).index()] = pmc.PyNode(sym_idx[0]).index() return sym_map
def match_edgeRing_translateY(): '''Select an edge loop on a "track" and then matches the y values so it's flat Args: (None) Returns: (None) Usage: match_edgeRing_translateY() ''' for edge in pm.ls(sl=True,fl=True): vert_inside, vert_outside = pm.ls( pm.polyListComponentConversion( edge, toVertex=True ), fl=True ) pos_inside = vert_inside.getPosition(space='world') pos_outside = vert_outside.getPosition(space='world') new_pos = [pos_outside[0], pos_inside[1], pos_outside[2]] vert_outside.setPosition( new_pos, space='world' )
def middle(self,s): if self.midCtrlCheckBox.getValue() == 1: number = self.randSliderT.getValue()/10 else: number = 0.5 #use input field data to determine flat uv set flatUvSet = self.findFlatUvSet(s) #get tips of geo and split to top and bottom pairs pair1, pair2 = self.findTips(s, flatUvSet) #select edges going the length on the cards and list as vertices pm.polyUVSet(s, currentUVSet =1, uvSet=flatUvSet)###not sure that I need it side1Edge = pm.polySelect(s, ass = 1, shortestEdgePathUV = (pair1[0].getUVIndices(str(flatUvSet))[0], pair2[0].getUVIndices(str(flatUvSet))[0])) side1 = pm.ls(pm.polyListComponentConversion(side1Edge, fe =1, tv =1), fl = 1) side2Edge = pm.polySelect(s, ass = 1, shortestEdgePathUV = (pair1[1].getUVIndices(str(flatUvSet))[0], pair2[1].getUVIndices(str(flatUvSet))[0])) side2 = pm.ls(pm.polyListComponentConversion(side2Edge, fe =1, tv =1), fl = 1) #select bottom verts and walk(traverse) to the middle of the geo on both sides mid1 = pm.ls(self.traverse(start = pair1[0], listToWalk = side1, multiplyBy = number )) mid2 = pm.ls(self.traverse(start = pair1[1], listToWalk = side2, multiplyBy = number )) #select shortest path between the 2 middle points and add to the middleL list MidLine = pm.polySelect(s, ass = 1, shortestEdgePathUV = (mid1[0].getUVIndices(str(flatUvSet))[0], mid2[0].getUVIndices(str(flatUvSet))[0])) pm.select(cl = 1) return MidLine
def getEdgeRingList(verts): # iterate verts from 1 to -1 edgering = [] for vert in verts[1:-1]: connectedVerts = vert.connectedVertices() for adjVert in connectedVerts: if adjVert not in verts: break edgeVerts = [vert, adjVert] edge = pm.polyListComponentConversion(edgeVerts, fv=True, te=True, internal=True) edgering.append(edge) return edgering
def match_shell(self, maxrange): # FIXME MAX Range set snapuvs = pm.ls(pm.polyListComponentConversion(tuv=True), sl=True, fl=True) # getUVs to match objs = [i.getShape() for i in pm.ls(hl=True, fl=True)] alluvs = pm.ls(pm.polyListComponentConversion(objs, tuv=True), fl=True) alluvs = sorted(set(alluvs) - set(snapuvs)) # get all uvs and subtract from snap uvs snappos = [pm.polyEditUV(i, q=True) for i in snapuvs] # Get pos for snap and all allpos = [pm.polyEditUV(i, q=True) for i in alluvs] for i in range(len(snapuvs)): inrange = [] for j in range(len(alluvs)): x = snappos[i][0] - allpos[j][0] y = snappos[i][1] - allpos[j][1] dist = math.sqrt((x ** 2) + (y ** 2)) if dist < maxrange: inrange.append((allpos[j], dist)) if inrange: inrange = min(inrange, key=lambda x: x[1]) pm.polyEditUV(snapuvs[i], u=inrange[0][0], v=inrange[0][1], r=False)
def bdJointsOnEdge(): edgeSelection = pm.ls(sl=True) vertices = pm.polyListComponentConversion(edgeSelection, fromEdge=1 , tv=1) pm.select(vertices) vertices = pm.ls(sl=1,fl=1) mesh = vertices[0].name().split('.')[0].replace('Shape','') locators = [] for vert in vertices: #vertUV = vert.getUV() uv = pm.polyListComponentConversion(vert, fromVertex =1 , tuv=1) vertUV = pm.polyEditUV(uv[0] , query = True) locator = pm.spaceLocator(n='loc_%s'%vert) locators.append(locator) cnstr = pm.animation.pointOnPolyConstraint(vert,locator) pm.setAttr('%s.%sU0'%(cnstr,mesh),vertUV[0]) pm.setAttr('%s.%sV0'%(cnstr,mesh),vertUV[1]) for loc in locators: pm.select(cl=1) jnt = pm.joint(p=(0,0,0),name=loc.name().replace('loc','jnt')) print jnt pm.pointConstraint(loc,jnt,mo=False)
def mergeCenterEdgeIslands(edges): ''' Args: edges (list(pm.nt.general.MeshEdge)): edges to be clustered Returns (list(pm.nt.Transform)): list of cluster transforms Usage: islands = mergeCenterEdgeIslands(pm.ls(sl=True,fl=True)) ''' islands = getEdgeIslands(edges) for island in islands: islandVerts = pm.ls( pm.polyListComponentConversion(island, tv=True), fl=True ) pm.select(islandVerts, r=True) pm.polyMergeVertex( islandVerts, d=1, am=True, mtc=True ) return islands
def clusterEdgeIslands(edges): ''' Args: edges (list(pm.nt.general.MeshEdge)): edges to be clustered Returns (list(pm.nt.Transform)): list of cluster transforms Usage: clusterEdgeIslands(pm.ls(sl=True,fl=True)) ''' transform = edges[0].node().getParent() islands = getEdgeIslands(edges) clusters = [] for index, island in enumerate(islands): islandVerts = pm.ls( pm.polyListComponentConversion(island, tv=True), fl=True ) clusters.append( pm.cluster(islandVerts,n=transform.replace('GEO','%02d_CLUSTER'%index)) ) return clusters
def bdJointOnSelCenter(): selection = pm.ls(sl=True, fl=True) vertices = pm.polyListComponentConversion(selection, toVertex=True) pm.select(vertices) selection = pm.ls(sl=True, fl=True) averagePos = dt.Vector(0, 0, 0) if type(selection[0]).__name__ == "MeshVertex": numSel = len(selection) for sel in selection: vtxPos = sel.getPosition(space="world") averagePos = averagePos + vtxPos averagePos = averagePos / numSel pm.select(cl=True) joint = pm.joint(p=[averagePos.x, averagePos.y, averagePos.z], radius=0.2)
def create(self, curveType, spans, selOnly): sel = pm.selected() cmds.CreateCurveFromPoly() curve = pm.selected() pm.rebuildCurve(curve, spans=spans) # set UI curve self.uiObj.setCurrentCurve(curve[0].shortName()) if curveType == 1: pm.nurbsCurveToBezier() pm.delete(curve, ch=True) # Deform if selOnly: sel = pm.polyListComponentConversion(sel, fe=True, tv=True) self.wire = pm.wire(sel, w=curve) else: #Object self.wire = pm.wire(sel[0].node(), w=curve)
def face_avg_uv(face): """ Gets the average uv position for all the uv points on a face and return the uv floor value Args: face (pm.general.MeshFace): given face to be queried Returns: [int, int]: list 2 integers representing u and v coordinates """ face_uvs = pm.ls(pm.polyListComponentConversion(face, tuv=True), fl=True) uvs = {} for face_uv in face_uvs: u, v = pm.polyEditUV(face_uv, q=True) uvs.setdefault('u',[]) uvs.setdefault('v',[]) uvs['u'].append(u) uvs['v'].append(v) avg_u = int(math.floor(sum(uvs['u'])/len(uvs['u']))) avg_v = int(math.floor(sum(uvs['v'])/len(uvs['v']))) return [avg_u+1, avg_v+1]
def relax(): # check the selection selection = pm.ls(sl=1) if not selection: return # convert the selection to vertices verts = pm.ls(pm.polyListComponentConversion(tv=1)) if not verts: return shape = verts[0].node() # duplicate the geometry dup = shape.duplicate()[0] dup_shape = dup.getShape() # now relax the selected vertices of the original shape pm.polyAverageVertex(verts, i=1, ch=0) # now transfer point positions using transferAttributes ta_node = pm.transferAttributes( dup, verts, transferPositions=True, transferNormals=False, transferUVs=False, transferColors=False, sampleSpace=0, searchMethod=0, flipUVs=False, colorBorders=1, ) # delete history pm.delete(shape, ch=1) # delete the duplicate surface pm.delete(dup) # reselect selection pm.select(selection)
def get_shells(self): if len(self.shells): pm.warning('Class is already a shell') return cursel = pm.selected() self.shells = [] for uv in self.uvs: found = False for shell in self.shells: if uv in shell.uvs: found = True if not found: pm.select(uv) pm.mel.polySelectBorderShell(0) sel = pm.ls(pm.polyListComponentConversion(tuv=True), fl=True) thisShell = UV(sel) thisShell.get_bounds() self.shells.append(thisShell) pm.select(cursel) return self.shells
def rig_getSkinClusterInfluencedMostFace(mesh, skinCluster, influence, *args): '''Takes in a list of meshes to cut pieces that are influenced by influence object (joint) Args: mesh (list(pm.nt.Transform)): mesh to get faces from skinCluster (pm.nt.SkinCluster): skinCluster to query influence (pm.nt.Joint): figures out the faces influenced based on this one joint Returns: list (pm.nt.Transform): list of faces that are most influenced by an influence/joint Usage: rig_getSkinClusterInfluencedMostFace('pm.ls(sl=True)[0]', pm.PyNode('skinCluster1'), pm.PyNode('joint1') ) ''' selectFaces=[] influences = skinCluster.getWeightedInfluence() if influence in influences: infVerts = skinCluster.getPointsAffectedByInfluence(influence)[0] if not infVerts: pm.warning("Skipping %s %s no weight on object %s" % (skinCluster, influence, mesh.name())) else: faces = pm.ls(pm.polyListComponentConversion(infVerts, fv=True, tf=True), fl=True) for face in faces: infList = pm.skinPercent(skinCluster, face, t=None, q=True) infWeights = [] #TODO figure out the inf list setup for inf in infList: infWeights.append( pm.skinPercent(skinCluster, face, t=inf, q=True) ) maxWeight = 0.0 maxInf = '' for i, inf in enumerate(infList): if infWeights[i] > maxWeight: maxWeight = infWeights[i] maxInf = inf if maxInf == influence: selectFaces.append(face) else: pm.warning('%s is not an influence on %s' % (influence, skinCluster)) return pm.ls(selectFaces, fl=True)
import pymel.core as pm hiddenFaces = [] for j in range(len(pm.selected())): for i in pm.selected()[j]: if i.getArea() < 1.0e-4: hiddenFaces.append(i) print hiddenFaces result = pm.confirmDialog(title='!!!', button=['Yes','No'], defaultButton='Yes', cancelButton='No', dismissString='No', m="hidden faces number: {0} Kill them?".format(len(hiddenFaces))) #pm.select(hiddenFaces) #pm.delete(hiddenFaces) if result == 'Yes': for face in hiddenFaces: pm.select(face) pm.polyListComponentConversion(fromFace = True, toVertex = True) pm.polyMergeVertex( distance=0.0 ) else: pm.select(hiddenFaces)
def prepSel(self, sel): sel = pm.polyListComponentConversion(sel, tv=True) pm.select(sel) pm.polySelectConstraint(pp=3, type=0x0001) verts = pm.ls(sl=True, fl=True) return verts
def edge_to_jnt(): selection = pm.ls(sl=1) vtx = pm.polyListComponentConversion(selection, fe=True, tv=1) pm.select(vtx) vtx = pm.ls(sl=1, fl=1)
def find_intersection_other(self, mesh1, mesh2): mesh1_dagPath = mesh1.__apimdagpath__() # mesh的节点路径 mesh2_dagPath = mesh2.__apimdagpath__() mesh1_itr = OpenMaya.MItMeshEdge(mesh1_dagPath) # MItMeshEdge 多边形边迭代器 mesh2_mesh = OpenMaya.MFnMesh(mesh2_dagPath) util = OpenMaya.MScriptUtil() # MScriptUtil 实用程序类,用于在Python中使用指针和引用 edge_len_ptr = util.asDoublePtr() # asDoublePtr() 返回指向此类数据的双指针。 edge_list = set() while not mesh1_itr.isDone(): mesh1_itr.getLength(edge_len_ptr) # getLength()返回当前边的长度。 edge_len = util.getDouble( edge_len_ptr) # getDouble() 获取Double型参数的值 start_pt = mesh1_itr.point( 0, OpenMaya.MSpace.kWorld) # point()返回当前边的指定顶点的位置。 end_pt = mesh1_itr.point(1, OpenMaya.MSpace.kWorld) # MSpace 空间转换标识符 # kWorld 对象世界坐标系的数据 raySource = OpenMaya.MFloatPoint( start_pt) # MFloatPoint 以浮点类型来实现处理点 rayDirection = OpenMaya.MFloatVector( end_pt - start_pt) # MFloatVector 浮点数向量的向量类 faceIds = None triIds = None idsSorted = False # 不排序 space = OpenMaya.MSpace.kWorld maxParam = edge_len # 边长度、搜索半径 testBothDirections = False # accelParams = mesh2_mesh.autoUniformGridParams( ) # autoUniformGridParams创建一个MMeshIsectAccelParams配置对象 sortHits = False hitPoints = OpenMaya.MFloatPointArray() # MFloatPoint数据类型的矩阵 hitRayParams = None hitFaces = OpenMaya.MIntArray() # int数据类型矩阵 hitTriangles = None hitBary1s = None hitBary2s = None rayDirection.normalize() # 单位化 gotHit = mesh2_mesh.allIntersections( raySource, rayDirection, faceIds, triIds, idsSorted, space, maxParam, testBothDirections, accelParams, sortHits, hitPoints, hitRayParams, hitFaces, hitTriangles, hitBary1s, hitBary2s) # allIntersections 查找从raySource开始并与mesh在rayDirection中传播的射线的所有交点。 # 如果faceIds和triIds均为NULL,则将考虑网格中的所有三角形面片。 # 返回值True、False if gotHit: edge_list.add(mesh1_itr.index()) # 把边的序号存入edge_list mesh1_itr.next() # 获取碰撞的边再通过边转面 edge_list = [ "%s.e[%s]" % (mesh1_dagPath.fullPathName(), edge_id) for edge_id in edge_list ] facelist = pm.polyListComponentConversion(edge_list, fe=True, tf=True) # polyListComponentConversion 将多边形组件从一种或多种类型转换为另一种或多种类型 # fromEdge(fe)toFace(tf) # 展平序号 return pm.ls(facelist, flatten=True)
def create_ribbons(self, side, components_type, selection, how_many_ctrls): if components_type != "face": if components_type == "edge": vertices_from_selection = pmc.polyListComponentConversion(selection, fromEdge=1, toVertex=1) vertices = pmc.ls(vertices_from_selection, flatten=1) vertices_from_first_edge = pmc.ls(pmc.polyListComponentConversion(selection[0], fromEdge=1, toVertex=1), flatten=1) edges_from_point = pmc.ls(pmc.polyListComponentConversion(vertices_from_first_edge[0], fromVertex=1, toEdge=1), flatten=1) vertices_from_edges = pmc.ls(pmc.polyListComponentConversion(edges_from_point, toVertex=1, fromEdge=1, border=1), flatten=1) next_vertex = [vertex for vertex in vertices_from_edges if vertex in vertices] if len(next_vertex) == 1: first_vertex = pmc.ls(vertices_from_first_edge[0])[0] else: first_vertex = pmc.ls(vertices_from_first_edge[1])[0] vertices.remove(first_vertex) vertices.insert(0, first_vertex) else: vertices = selection ordered_vertices = rig_lib.continuous_check_and_reorder_vertex_list(vertices, self.model.module_name) vertices_world_pos = [] skn_jnts = [] for i, vertex in enumerate(ordered_vertices): vertices_world_pos.append(pmc.xform(vertex, q=1, ws=1, translation=1)) pmc.select(cl=1) jnt = pmc.joint(p=(0, 0, 0), n="{0}_{1}_{2}_SKN".format(self.model.module_name, side, i)) jnt.setAttr("translate", vertices_world_pos[i]) jnt.setAttr("radius", 0.1) skn_jnts.append(jnt) front_curve = pmc.curve(d=3, p=vertices_world_pos, n="{0}_{1}_nurbsSurface_guide_01".format(self.model.module_name, side)) back_curve = pmc.duplicate(front_curve, n="{0}_{1}_nurbsSurface_guide_02".format(self.model.module_name, side))[0] if self.model.loft_axis == "X": front_curve.setAttr("translateX", 0.1) back_curve.setAttr("translateX", -0.1) elif self.model.loft_axis == "Y": front_curve.setAttr("translateY", 0.1) back_curve.setAttr("translateY", -0.1) else: front_curve.setAttr("translateZ", 0.1) back_curve.setAttr("translateZ", -0.1) surface = pmc.loft(back_curve, front_curve, ar=1, ch=0, d=1, uniform=0, n="{0}_{1}_ribbons_NURBSSURFACE".format(self.model.module_name, side))[0] surface = pmc.rebuildSurface(surface, ch=0, du=1, dv=3, dir=2, kcp=1, kr=0, rt=0, rpo=1)[0] pmc.delete(front_curve) pmc.delete(back_curve) pmc.parent(surface, self.parts_grp) self.jnts_to_skin.append(skn_jnts) follicles = [] for i, jnt in enumerate(skn_jnts): follicle_shape = pmc.createNode("follicle", n="{0}_{1}_{2}_FOLShape".format(self.model.module_name, side, i)) follicle = follicle_shape.getParent() follicle.rename("{0}_{1}_{2}_FOL".format(self.model.module_name, side, i)) follicle_shape.outTranslate >> follicle.translate follicle_shape.outRotate >> follicle.rotate surface.getShape().local >> follicle_shape.inputSurface surface.getShape().worldMatrix[0] >> follicle_shape.inputWorldMatrix point_on_surface = pmc.createNode("closestPointOnSurface", n=str(jnt) + "CPS") surface.getShape().local >> point_on_surface.inputSurface point_on_surface.setAttr("inPosition", pmc.xform(jnt, q=1, ws=1, translation=1)) follicle_shape.setAttr("parameterU", point_on_surface.getAttr("parameterU")) follicle_shape.setAttr("parameterV", point_on_surface.getAttr("parameterV")) pmc.delete(point_on_surface) pmc.parent(jnt, follicle, r=0) follicles.append(follicle) pmc.parent(follicle, self.jnt_input_grp) pmc.select(cl=1) start_jnt = pmc.joint(p=(0, 0, 0), n="{0}_{1}_start_JNT".format(self.model.module_name, side)) start_jnt.setAttr("radius", 0.2) pmc.select(cl=1) end_jnt = pmc.joint(p=(0, 0, 0), n="{0}_{1}_end_JNT".format(self.model.module_name, side)) end_jnt.setAttr("radius", 0.2) pmc.select(cl=1) mid_jnt = pmc.joint(p=(0, 0, 0), n="{0}_{1}_mid_JNT".format(self.model.module_name, side)) mid_jnt.setAttr("radius", 0.2) pmc.select(cl=1) start_mid_jnt = pmc.joint(p=(0, 0, 0), n="{0}_{1}_start_mid_JNT".format(self.model.module_name, side)) start_mid_jnt.setAttr("radius", 0.2) pmc.select(cl=1) mid_end_jnt = pmc.joint(p=(0, 0, 0), n="{0}_{1}_mid_end_JNT".format(self.model.module_name, side)) mid_end_jnt.setAttr("radius", 0.2) ctrl_jnts_pos = pmc.createNode("pointOnSurfaceInfo", n="{0}_{1}_PSI".format(self.model.module_name, side)) surface.getShape().local >> ctrl_jnts_pos.inputSurface ctrl_jnts_pos.setAttr("parameterU", 0.5) ctrl_jnts_pos.setAttr("parameterV", 0.0) pmc.refresh() start_jnt.setAttr("translate", ctrl_jnts_pos.getAttr("position")) if how_many_ctrls == "7": ctrl_jnts_pos.setAttr("parameterV", 0.3) else: ctrl_jnts_pos.setAttr("parameterV", 0.25) pmc.refresh() start_mid_jnt.setAttr("translate", ctrl_jnts_pos.getAttr("position")) ctrl_jnts_pos.setAttr("parameterV", 0.5) pmc.refresh() mid_jnt.setAttr("translate", ctrl_jnts_pos.getAttr("position")) if how_many_ctrls == "7": ctrl_jnts_pos.setAttr("parameterV", 0.7) else: ctrl_jnts_pos.setAttr("parameterV", 0.75) pmc.refresh() mid_end_jnt.setAttr("translate", ctrl_jnts_pos.getAttr("position")) ctrl_jnts_pos.setAttr("parameterV", 1.0) pmc.refresh() end_jnt.setAttr("translate", ctrl_jnts_pos.getAttr("position")) if how_many_ctrls == "7": pmc.select(cl=1) start_quarter_jnt = pmc.joint(p=(0, 0, 0), n="{0}_{1}_start_quarter_JNT".format(self.model.module_name, side)) start_quarter_jnt.setAttr("radius", 0.2) pmc.select(cl=1) quarter_end_jnt = pmc.joint(p=(0, 0, 0), n="{0}_{1}_quarter_end_JNT".format(self.model.module_name, side)) quarter_end_jnt.setAttr("radius", 0.2) ctrl_jnts_pos.setAttr("parameterV", 0.15) pmc.refresh() start_quarter_jnt.setAttr("translate", ctrl_jnts_pos.getAttr("position")) ctrl_jnts_pos.setAttr("parameterV", 0.85) pmc.refresh() quarter_end_jnt.setAttr("translate", ctrl_jnts_pos.getAttr("position")) ctrls_jnt = [start_jnt, start_quarter_jnt, start_mid_jnt, mid_jnt, mid_end_jnt, quarter_end_jnt, end_jnt] else: ctrls_jnt = [start_jnt, start_mid_jnt, mid_jnt, mid_end_jnt, end_jnt] pmc.delete(ctrl_jnts_pos) ctrls = [] ctrls_fol = [] for jnt in ctrls_jnt: if side == "bot": jnt.setAttr("jointOrientX", 180) if jnt.getAttr("translateX") < -0.05: jnt.setAttr("jointOrientY", 180) follicle_shape = pmc.createNode("follicle", n=str(jnt).replace("_JNT", "_FOLShape")) follicle = follicle_shape.getParent() follicle.rename(str(jnt).replace("_JNT", "_FOL")) follicle_shape.outTranslate >> follicle.translate follicle_shape.outRotate >> follicle.rotate self.mesh_to_follow.getShape().outMesh >> follicle_shape.inputMesh self.mesh_to_follow.getShape().worldMatrix[0] >> follicle_shape.inputWorldMatrix point_on_mesh = pmc.createNode("closestPointOnMesh", n=str(jnt) + "CPM") self.mesh_to_follow.getShape().outMesh >> point_on_mesh.inMesh point_on_mesh.setAttr("inPosition", pmc.xform(jnt, q=1, ws=1, translation=1)) follicle_shape.setAttr("parameterU", point_on_mesh.getAttr("parameterU")) follicle_shape.setAttr("parameterV", point_on_mesh.getAttr("parameterV")) pmc.delete(point_on_mesh) ctrls_fol.append(follicle) pmc.select(clear=1) ctrl_shape = pmc.circle(c=(0, 0, 0), nr=(0, 0, 1), sw=360, r=0.5, d=3, s=8, n=str(jnt).replace("_JNT", "_ctrl_Shape"), ch=0)[0] ctrl = rig_lib.create_jnttype_ctrl(name=str(jnt).replace("_JNT", "_CTRL"), shape=ctrl_shape) pmc.select(clear=1) ctrl_ofs = pmc.joint(p=(0, 0, 0), n=str(ctrl).replace("_CTRL", "_ctrl_OFS")) ctrl_ofs.setAttr("drawStyle", 2) ctrl_fix_r = pmc.joint(p=(0, 0, 0), n=str(ctrl).replace("_CTRL", "_ctrl_rotate_FIX")) ctrl_fix_r.setAttr("drawStyle", 2) ctrl_fix_r.setAttr("rotateOrder", 5) ctrl_fix_t = pmc.joint(p=(0, 0, 0), n=str(ctrl).replace("_CTRL", "_ctrl_translate_FIX")) ctrl_fix_t.setAttr("drawStyle", 2) pmc.parent(ctrl, ctrl_fix_t) pmc.parent(ctrl_ofs, follicle) ctrl_ofs.setAttr("translate", (0, 0, 0)) ctrl_ofs.setAttr("rotate", (0, 0, 0)) ctrl_ofs.setAttr("jointOrient", (0, 0, 0)) ctrl_ofs_orientation_loc = pmc.spaceLocator(p=(0, 0, 0), n="{0}_orientation_LOC".format(ctrl_ofs)) pmc.parent(ctrl_ofs_orientation_loc, jnt, r=1) pmc.parent(ctrl_ofs_orientation_loc, follicle, r=0) ctrl_ofs.setAttr("jointOrient", ctrl_ofs_orientation_loc.getAttr("rotate")) pmc.delete(ctrl_ofs_orientation_loc) invert_ctrl_translate = pmc.createNode("multiplyDivide", n=str(ctrl) + "invert_translate_MDL") invert_ctrl_rotate = pmc.createNode("multiplyDivide", n=str(ctrl) + "invert_rotate_MDL") ctrl.translate >> invert_ctrl_translate.input1 invert_ctrl_translate.setAttr("input2", (-1, -1, -1)) invert_ctrl_translate.output >> ctrl_fix_t.translate ctrl.rotate >> invert_ctrl_rotate.input1 invert_ctrl_rotate.setAttr("input2", (-1, -1, -1)) invert_ctrl_rotate.output >> ctrl_fix_r.rotate ctrl_cvs = ctrl.cv[:] for cv in ctrl_cvs: pmc.move(cv, 0.5, moveZ=1, ws=1, wd=1, r=1) pmc.move(cv, 0.1, moveY=1, ls=1, wd=1, r=1) jnt_ofs = pmc.duplicate(jnt, n=str(jnt).replace("_JNT", "_jnt_OFS"))[0] jnt_ofs.setAttr("drawStyle", 2) pmc.parent(jnt, jnt_ofs) ctrl.translate >> jnt.translate ctrl.rotate >> jnt.rotate ctrl.scale >> jnt.scale ctrls.append(ctrl) pmc.parent(jnt_ofs, self.parts_grp) pmc.parent(follicle, self.ctrl_input_grp) pmc.select(cl=1) pmc.skinCluster(ctrls_jnt, surface, bm=0, dr=4.0, mi=2, nw=1, sm=0, tsb=1, wd=0) return skn_jnts, surface, follicles, ctrls_jnt, ctrls_fol, ctrls else: pmc.error("faces aren't support yet")
def LeaveFace(uvls=None,**op): if uvls is None: uvls=[] if op.get('tg'): tgMesh=op.get('tg') else: tgMesh='Null' if tgMesh=='Null' or len(uvls)==0: return None pm.select( pm.polyListComponentConversion(tgMesh, tf=1) ) tgAllFace=pm.ls(sl=1,fl=1) pm.select( pm.polyListComponentConversion(uvls, tf=1) ) tgSlFace=pm.ls(sl=1,fl=1) delFaceLs=list( set(tgAllFace)-set(tgSlFace) ) pm.delete(delFaceLs) slMesh=pm.ls(sl=1)[0] uvShellLs=UVShell(slMesh) copyMeshLs=[] for i in xrange(len(uvShellLs)): copyMeshLs.append( pm.duplicate(slMesh, n='%sCopy%d_geo'% (slMesh.name(),i+1) )[0] ) slTgUVLs=ChangeUVListTarget(uvShellLs[i],tg=copyMeshLs[i]) LeaveFace(slTgUVLs, tg=copyMeshLs[i]) if len(copyMeshLs)>1: dvdMesh=pm.polyUnite(copyMeshLs,ch=0,muv=1, cp=0,n='%sDvd_geo'% slMesh.name() )[0] else: dvdMesh=copyMeshLs[0].rename('%sDvd_geo'% slMesh.name()) unfoldMesh=pm.duplicate(dvdMesh, n='%sUnfold_geo'% slMesh.name() )[0] pm.select( pm.polyListComponentConversion(unfoldMesh, tuv=1) ) unfoldMeshUVLs=pm.ls(sl=1,fl=1) for ufuv in unfoldMeshUVLs: uvCoor=pm.polyEditUV(ufuv,q=1,u=1) tgVtx=pm.polyListComponentConversion(ufuv, tv=1)[0] pm.move(tgVtx,[ uvCoor[0]*5, 0.0, uvCoor[1]*-5 ],ws=1)
def pickVtx(): edges = pm.ls(sl=1) vtx = pm.polyListComponentConversion(edges, fe=1, tv=1) vtx = pm.ls(vtx, fl=1) return vtx
def bdJointOnSelCenter(): selection = pm.ls(sl=True, fl=True) vtxPosArray = [] vertices = pm.polyListComponentConversion(selection, toVertex=True) pm.select(vertices) selection = pm.ls(sl=True, fl=True) if type(selection[0]).__name__ == 'MeshVertex': for sel in selection: vtxPos = sel.getPosition(space='world') print vtxPos, sel.name() vtxPosArray.append(om.MVector(vtxPos[0], vtxPos[1], vtxPos[2])) loc = pm.spaceLocator(p=vtxPos) loc.centerPivots() #vtx1Pos = selection[0].getPoint(1,space='world') #vtxPos.append(om.MVector(vtx1Pos[0],vtx1Pos[1],vtx1Pos[2])) area = 0 centroids = [] areas = [] for i in range(1, len(vtxPosArray) - 1): area = area + ( (vtxPosArray[i] - vtxPosArray[0]) ^ (vtxPosArray[i + 1] - vtxPosArray[0])).length() / 2.0 areas.append( ((vtxPosArray[i] - vtxPosArray[0]) ^ (vtxPosArray[i + 1] - vtxPosArray[0])).length() / 2.0) centroid = (vtxPosArray[0] + vtxPosArray[i] + vtxPosArray[i + 1]) / 3.0 centroids.append(centroid) loc = pm.spaceLocator(p=[centroid.x, centroid.y, centroid.z]) loc.centerPivots() ''' center = om.MVector(0,0,0) print len(vtxPos), len(centroids), len(areas), 'MUIE' for i in range(len(centroids)): center = center + (centroids[i]*areas[i]) center = center/area pm.spaceLocator(p=[center.x,center.y,center.z],a=True) ''' ''' sumCrossProducts = om.MVector() normal = (vtxPos[0]^vtxPos[1]).normal() print normal.x,normal.y,normal.z for i in range(len(vtxPos)-1): sumCrossProducts += (vtxPos[i]^vtxPos[i+1]) area = (normal/2.0)*sumCrossProducts cx= cy = cz = 0 for i in range(len(vtxPos)-1): cx = cx + (vtxPos[i].x + vtxPos[i+1].x)*(vtxPos[i].x*vtxPos[i+1].y - vtxPos[i+1].x*vtxPos[i].y) cy = cy + (vtxPos[i].y + vtxPos[i+1].y)*(vtxPos[i].x*vtxPos[i+1].y - vtxPos[i+1].x*vtxPos[i].y) cz = cx + (vtxPos[i].z + vtxPos[i+1].z)*(vtxPos[i].x*vtxPos[i+1].z- vtxPos[i+1].x*vtxPos[i].z) cx = cx/(6.0*area) cy = cy/(6.0*area) cz = cz/(6.0*area) ''' print area #pm.spaceLocator(p=[cx,cy,cz]) if type(selection[0]).__name__ == 'MeshFace': for sel in selection: print sel.getArea(), pm.objectCenter(sel) center = pm.objectCenter(sel) pm.spaceLocator(p=[center[0], center[1], center[2]])
def main(): sel_list = pm.ls(pm.pickWalk(d="down"), ni=1, type="mesh") if not sel_list: QtWidgets.QMessageBox.warning(None, u"警告", u"请选择一个模型") return sel = sel_list[0] # pm.undoInfo(ock=1) num_list, total = sel.getUvShellsIds() shell_dict = {num: i for i, num in enumerate(num_list)} border_dict = defaultdict(dict) uv_dict = {} for i, uv in shell_dict.items(): pm.select(sel.map[uv]) pm.polySelectConstraint(uv=1, bo=0, m=2) uv_list = pm.ls(pm.polySelectConstraint(uv=0, rs=1), fl=1) face_list = pm.polyListComponentConversion(fuv=1, tf=1) border_list = pm.ls(pm.polyListComponentConversion(fuv=1, te=1, bo=1), fl=1) _border_list = [e.index() for e in border_list] edge_dict = { edge: { face.getUVIndex(j): face.getUV(j) for j in range(face.polygonVertexCount()) } for face in pm.ls(face_list, fl=1) for edge in face.getEdges() if edge in _border_list } border_dict = {} border_uvs = pm.polyListComponentConversion(border_list, fe=1, tuv=1) border_uvs = [uv for uv in pm.ls(border_uvs, fl=1) if uv in uv_list] for uv in border_uvs: edges = pm.polyListComponentConversion(uv, fuv=1, te=1) edges = [e for e in pm.ls(edges, fl=1) if e in border_list] uvs = pm.polyListComponentConversion(edges, fe=1, tuv=1) uvs = [ _uv for _uv in pm.ls(uvs, fl=1) if _uv != uv and _uv in border_uvs ] border_dict[uv] = uvs print(border_dict) break # print(json.dumps(edge_dict)) return # TODO 遍历 polygon 找 UV 对应关系 dag_path = sel.__apimdagpath__() itr = OpenMaya.MItMeshPolygon(dag_path) util = OpenMaya.MScriptUtil() edge_dict = defaultdict(list) while not itr.isDone(): face_idx = itr.index() uv = {} for i in range(itr.polygonVertexCount()): idx_ptr = util.asIntPtr() u_ptr = util.asFloatPtr() v_ptr = util.asFloatPtr() itr.getUVIndex(i, idx_ptr, u_ptr, v_ptr) idx = util.getInt(idx_ptr) u = util.getFloat(u_ptr) v = util.getFloat(v_ptr) uv[idx] = (u, v) edges = OpenMaya.MIntArray() itr.getEdges(edges) for i in range(edges.length()): edge = edges[i] edge_dict[edge].append({"uv": uv, "face_idx": face_idx}) itr.next() edge_list = [] for edge_idx, data in edge_dict.items(): print(len(data)) if len(data) == 1: edge_list.append(edge_idx) print(edge_list) # print(json.dumps(edge_dict)) return pm.progressWindow(title=u"获取 uv border", status=u"获取模型 uv border...", progress=0.0) for i, uv in shell_dict.items(): pm.progressWindow(e=1, progress=i / total * 100) # NOTES(timmyliang) 如果 uv 不在 0,1 象限则跳过 x, y = sel.getUV(uv) if not 0 < x < 1 or not 0 < y < 1: continue pm.select(sel.map[uv]) pm.polySelectConstraint(uv=1, bo=0, m=2) uv_list = pm.polySelectConstraint(t=0x0010, uv=0, bo=1, m=2, rs=1) uv_list = [_uv.currentItemIndex() for _uv in pm.ls(uv_list, fl=1)] pos_list = {uv: sel.getUV(uv) for uv in uv_list} x = sum([pos[0] for pos in pos_list.values()]) / len(pos_list) y = sum([pos[1] for pos in pos_list.values()]) / len(pos_list) uv_dict.update(pos_list) borders = pm.polyListComponentConversion(fuv=1, te=1, bo=1) borders = pm.ls(borders, fl=1) for uv in uv_list: edges = pm.polyListComponentConversion(sel.map[uv], fuv=1, te=1) edges = [e for e in pm.ls(edges, fl=1) if e in borders] uvs = pm.polyListComponentConversion(edges, fe=1, tuv=1) uvs = [_uv.currentItemIndex() for _uv in pm.ls(uvs, fl=1)] uvs = [_uv for _uv in uvs if _uv != uv and _uv in uv_list] border_dict[uv] = {"uvs": uvs, "center": (x, y)} pm.progressWindow(ep=1) pm.polySelectConstraint(uv=0, bo=0, rs=1) distant = 0.01 for uv, data in border_dict.items(): uvs = data.get("uvs", []) if len(uvs) <= 1: continue uv1, uv2 = uvs x, y = data.get("center") center = dt.Vector(x, y) pos = dt.Vector(*uv_dict[uv]) pos1 = dt.Vector(*uv_dict[uv1]) pos2 = dt.Vector(*uv_dict[uv2]) vec1 = pos - pos1 vec2 = pos2 - pos x, y = get_pt(pos, pos1, pos2, vec1, vec2, distant) pt = dt.Vector(x, y) vec = pos - pt line = pos - center # NOTE reverse if vec.dot(line) > 0: x, y = get_pt(pos, pos1, pos2, vec1, vec2, distant, True) sel.setUV(uv, x, y) face_list = pm.polyUVOverlap(sel.faces, oc=True) pm.undoInfo(cck=1)
def findIntersection(src, dst, *args): src_dagPath = src.__apimdagpath__() dst_dagPath = dst.__apimdagpath__() src_itr = OpenMaya.MItMeshEdge(src_dagPath) src_mesh = OpenMaya.MFnMesh(src_dagPath) dst_mesh = OpenMaya.MFnMesh(dst_dagPath) util = OpenMaya.MScriptUtil() edge_len_ptr = util.asDoublePtr() face_list = set() pt_list = set() edge_list = set() while not src_itr.isDone(): src_itr.getLength(edge_len_ptr) edge_len = util.getDouble(edge_len_ptr) start_pt = src_itr.point(0, OpenMaya.MSpace.kWorld) end_pt = src_itr.point(1, OpenMaya.MSpace.kWorld) raySource = OpenMaya.MFloatPoint(start_pt) rayDirection = OpenMaya.MFloatVector(end_pt - start_pt) faceIds = None triIds = None idsSorted = False space = OpenMaya.MSpace.kWorld maxParam = edge_len testBothDirections = False accelParams = dst_mesh.autoUniformGridParams() sortHits = False hitPoints = OpenMaya.MFloatPointArray() hitRayParams = None hitFaces = OpenMaya.MIntArray() hitTriangles = None hitBary1s = None hitBary2s = None # NOTE 方向向量一定要记得 normalize 否则结果不对 rayDirection.normalize() gotHit = dst_mesh.allIntersections( raySource, rayDirection, faceIds, triIds, idsSorted, space, maxParam, testBothDirections, accelParams, sortHits, hitPoints, hitRayParams, hitFaces, hitTriangles, hitBary1s, hitBary2s, ) if gotHit: face_list.update(list(hitFaces)) pt_list.update([hitPoints[i] for i in range(hitPoints.length())]) edge_list.add(src_itr.index()) src_itr.next() # TODO 测试获取到的碰撞点 | 这行代码生成的 locator 位置很奇怪 # [pm.spaceLocator(p=(pt.x,pt.y,pt.z)) for pt in pt_list] # NOTE 直接获取碰撞的面不太准确 # pm.select(["%s.f[%s]" % (dst_dagPath.fullPathName(),face_id) for face_id in face_list]) # NOTE 获取碰撞的边再通过边转面获取的穿插比较准确 edge_list = [ "%s.e[%s]" % (src_dagPath.fullPathName(), edge_id) for edge_id in edge_list ] pm.select(pm.polyListComponentConversion(edge_list, fe=True, tf=True))
import pymel.core as pm import re pm.selectPref(trackSelectionOrder=True) getSel = pm.ls(os=1) vtxGrp = pm.ls(pm.polyListComponentConversion(getSel,fe=1,tv=1),fl=1) vtxNum = len(vtxGrp) vtxPosGrp = [pm.xform(vtx, q=True, ws=True, t=True)for vtx in vtxGrp] tmpPoly = mc.polyCreateFacet(p=[tuple(vec) for vec in vtxPosGrp ])[0] pm.xform(tmpPoly,cp=1) centerPos = mc.xform(tmpPoly, q=True, ws=True, rp=True) distGrp = [((vec[0] - centerPos[0]) ** 2 + (vec[1] - centerPos[1]) ** 2 + (vec[2] - centerPos[2]) ** 2) ** 0.5 for vec in vtxPosGrp] dist = sum(distGrp)/vtxNum circle = pm.circle(s=vtxNum, r=dist, c=(0, 0, 0), d=3, ch=False)[0] pm.xform(circle, ws=True, t=tuple(centerPos)) wu = (vtxPosGrp[0][0] - centerPos[0]),(vtxPosGrp[0][1] - centerPos[1]),(vtxPosGrp[0][2] - centerPos[2]) pm.normalConstraint(tmpPoly,circle,aim=[0,0,1],u=[0,1,0],wu=(0,1,0)) e2vInfos= pm.polyInfo(getSel,ev=1) e2vDict = {} for info in e2vInfos: evList = [ int(i) for i in re.findall('\\d+', info) ] e2vDict.update(dict([(evList[0], evList[1:])])) # average normal
def vtxWalking(): ''' walk: selecionar o edge loop da mesh base criar uma curva a partir da selecao de edge um sistema de motion path sai criando locators espacados na curva crio uma nova curva a partir dos locators, essa vai ser a base do guide :return: ''' edgeList = pm.ls(sl=1, fl=1) print '############################################ ', edgeList vtxListOrig = {} pairVtxEdge = [] # guarda pares de vertices que compoem as edges vtxWidthOrdered = {} vtxWidthToCenterOrdered = {} vtxHeightOrdered = {} vtxListOrdinary = [] vtxListOrdinaryIndex = [] vtxListOrdinaryCoord = [] vtxPoleList = [] # list com vertices top, bttm, left, right for e, edge in enumerate(edgeList): vertConvert = pm.polyListComponentConversion(edge.name(), fe=True, tv=True) vtxListTemp = pm.ls(vertConvert, fl=1) # lista com os vertices de cada edge do loop # print edge pairVtxEdge.append(vtxListTemp) for vertice in vtxListTemp: vertIndex = int(vertice.split('[')[1] [:-1]) # identificamos o indice do vertice vtxListOrig.update( {vertIndex: vertice}) # adicionamos numa lista onde nao se repete indices # identificando qual eh o vertice central superior: currentbBbox = bbox(vertice) vtxWidth = currentbBbox['width'] vtxHeight = currentbBbox['height'] if vtxWidth < 0: vtxWidthToCenter = vtxWidth * -1 # todos os valores do eixo x eh positivo para encontrarmos o mais prox de zero # print 'current neg position: ', vtxWidth, ' _ ', vtxHeight else: vtxWidthToCenter = vtxWidth vtxWidthToCenterOrdered.update({vertIndex: vtxWidthToCenter}) vtxWidthOrdered.update({vertIndex: vtxWidth}) vtxHeightOrdered.update({vertIndex: vtxHeight}) # comparando nos dois eixos x sorted_widthToCenterVtx = sorted(vtxWidthToCenterOrdered.items(), key=operator.itemgetter(1)) sorted_widthVtx = sorted(vtxWidthOrdered.items(), key=operator.itemgetter(1)) # identificar qual dos dois vertices esta mais acima if vtxHeightOrdered[sorted_widthToCenterVtx[0][0]] > vtxHeightOrdered[ sorted_widthToCenterVtx[1][0]]: topVtx = vtxListOrig[sorted_widthToCenterVtx[0][0]] bttmVtx = vtxListOrig[sorted_widthToCenterVtx[1][0]] else: topVtx = vtxListOrig[sorted_widthToCenterVtx[1][0]] bttmVtx = vtxListOrig[sorted_widthToCenterVtx[0][0]] vtxPoleList.append(topVtx) vtxPoleList.append(bttmVtx) vtxListOrdinary.append(topVtx) leftVtx = vtxListOrig[sorted_widthVtx[-1][0]] vtxPoleList.append(leftVtx) RigthVtx = vtxListOrig[sorted_widthVtx[0][0]] vtxPoleList.append(RigthVtx) # encontrando o vertice a direita do primeiro # encontrando quais os vertices ao lado do primeiro e deixando na lista nearVtxList nearVtxList = [] for pair in pairVtxEdge: if topVtx in pair: tempPair = list(pair) tempPair.remove(topVtx) nearVtxList.append(tempPair[0]) # identificando qual dos dois vertices eh o da direita: tempVtxBox = None tempVtx = None for eachVtx in nearVtxList: currentBbox = bbox(eachVtx)['width'] if not tempVtxBox and not tempVtx: tempVtxBox = currentBbox tempVtx = eachVtx if currentBbox > tempVtxBox: leftNearVtx = eachVtx else: leftNearVtx = tempVtx vtxListOrdinary.append(leftNearVtx) # ordenando os demais vertices: for i in range(len(pairVtxEdge) - 2): pairOptions = [] for pairSet in pairVtxEdge: if vtxListOrdinary[-1] in pairSet: pairOptions.append(pairSet) for option in pairOptions: if option[0] in vtxListOrdinary and option[1] in vtxListOrdinary: pairOptions.remove(option) tempPair = list(pairOptions[0]) tempPair.remove(vtxListOrdinary[-1]) nextPair = tempPair[0] vtxListOrdinary.append(nextPair) # lista de coordenadas dos vertices do loop: for vtx in vtxListOrdinary: vtxIndex = vtx.split('[')[1][:-1] coord = bbox(vtx) #tempLoc = rigFunctions.cntrlCrv(name=vtx + 'temp', icone='null', cntrlSulfix='_loc') #tempLoc.setTranslation((coord['width'], coord['height'], coord['deph']), 'world') coordSet = ((coord['width'], coord['height'], coord['deph'])) vtxListOrdinaryCoord.append(coordSet) vtxListOrdinaryIndex.append(vtxIndex) print vtxListOrdinary print vtxListOrdinaryCoord print vtxListOrdinaryIndex print vtxPoleList return { 'vtxNameList': vtxListOrdinary, # retorna lista com nome da cada vtx na ordem 'vtxCoordList': vtxListOrdinaryCoord, # retorna lista com coordenadas dos vtx na ordem 'vtxIndexList': vtxListOrdinaryIndex, # retorna lista com indices dos vtx na ordem 'vtxPolesList': vtxPoleList # retorna lista com nomes dos vtx dos polos [top, bttm, left, rigth] }
def main(): sel_list = pm.ls(pm.pickWalk(d="down"), ni=1, type="mesh") if not sel_list: QtWidgets.QMessageBox.warning(None, u"警告", u"请选择一个模型") return sel = sel_list[0] # # NOTE(timmyliang) 获取法线贴图过滤出里外 # pm.mel.renderWindowRender("redoPreviousRender", "renderView") # texture_path = posixpath.join( # pm.workspace(q=1, rd=1), "turtle", "bakedTextures", "dilation.png" # ) # img = QtGui.QImage(texture_path) pm.undoInfo(ock=1) # TODO check overlap first num_list, total = sel.getUvShellsIds() shell_dict = {num: i for i, num in enumerate(num_list)} border_dict = defaultdict(dict) uv_dict = {} pm.progressWindow(title=u"获取 uv border", status=u"获取模型 uv border...", progress=0.0) for i, uv in shell_dict.items(): pm.progressWindow(e=1, progress=i / total * 100) # NOTES(timmyliang) 如果 uv 不在 0,1 象限则跳过 x,y = sel.getUV(uv) if not 0 < x < 1 or not 0 < y < 1: continue pm.select(sel.map[uv]) pm.polySelectConstraint(uv=1, bo=0, m=2) uv_list = pm.polySelectConstraint(t=0x0010, uv= 0, bo=1, m=2, rs=1) uv_list = [_uv.currentItemIndex() for _uv in pm.ls(uv_list, fl=1)] pos_list = {uv: sel.getUV(uv) for uv in uv_list} x = sum([pos[0] for pos in pos_list.values()]) / len(pos_list) y = sum([pos[1] for pos in pos_list.values()]) / len(pos_list) uv_dict.update(pos_list) borders = pm.polyListComponentConversion(fuv=1, te=1, bo=1) borders = pm.ls(borders, fl=1) for uv in uv_list: edges = pm.polyListComponentConversion(sel.map[uv], fuv=1, te=1) edges = [e for e in pm.ls(edges, fl=1) if e in borders] uvs = pm.polyListComponentConversion(edges, fe=1, tuv=1) uvs = [_uv.currentItemIndex() for _uv in pm.ls(uvs, fl=1)] uvs = [_uv for _uv in uvs if _uv != uv and _uv in uv_list] border_dict[uv] = {"uvs": uvs, "center": (x, y)} pm.progressWindow(ep=1) pm.polySelectConstraint(uv=0,bo=0, rs=1) distant = 0.01 for uv, data in border_dict.items(): uvs = data.get("uvs",[]) if len(uvs) <= 1: continue uv1, uv2 = uvs x, y = data.get("center") center = dt.Vector(x, y) pos = dt.Vector(*uv_dict[uv]) pos1 = dt.Vector(*uv_dict[uv1]) pos2 = dt.Vector(*uv_dict[uv2]) vec1 = pos - pos1 vec2 = pos2 - pos x,y = get_pt(pos,pos1,pos2,vec1,vec2,distant) pt = dt.Vector(x,y) vec = pos - pt line = pos - center # NOTE reverse if vec.dot(line) > 0: x,y = get_pt(pos,pos1,pos2,vec1,vec2,distant,True) sel.setUV(uv, x, y) face_list = pm.polyUVOverlap( sel.faces,oc=True ) pm.undoInfo(cck=1)