def sew_uv(self): # FIXME edges = pm.filterExpand(ex=False, selectionMask=32) uvs = pm.filterExpand(ex=False, selectionMask=35) if edges: pm.polyMapSew() if uvs: pm.mel.performPolyMergeUV(0)
def createBevelSet(name='MWBevelSet#', edges=None): ''' :Reference: `CreateSet;` `performCreateSet false;` performCreateSet in C:/Program Files/Autodesk/Maya2018/scripts/others/performCreateSet.mel ''' # TODO: Make the set's name be the mesh name. if edges is None: edges = pm.filterExpand(sm=32, ex=True) else: edges = pm.filterExpand(edges, sm=32, ex=True) pm.select(cl=True) MWBevelSet = None if edges: MWBevelSet = pm.sets(name=name) MWBevelPartition = createPartition(MWBevelSet) # pm.sets(*edges, forceElement=MWBevelSet) MWBevelSet.forceElement(edges) # forceElement doesn't always work. objestSetsContainingEdges = getObjectSetsContainingEdgesUsingAPI2( edges) objestSetsContainingEdges.discard(MWBevelSet.name()) for objectSet in objestSetsContainingEdges: objectSet = pm.ls(objectSet, type='objectSet')[0] intersection = MWBevelSet.getIntersection(objectSet) not len(intersection) or objectSet.removeMembers(intersection) # TODO: Run bevel command on the edges. return MWBevelSet
def jointChainOrient( objs=[] ): # wip ''' update : 2015-04-29 ''' if objs: pm.selec(objs) objs = pm.ls(sl=True, o=True) if not objs: raise joints = pm.ls(sl=True, type='joint') if not joints: raise upMeshs = [] if pm.filterExpand(sm=12): upMeshs = [pm.PyNode(c) for c in pm.filterExpand(sm=12) ] # 업축으로 사용할 메쉬 # 조인트 오리엔트 조정: 메쉬의 가장 가까운 점의 노말을 조인트의 up으로 설정 if upMeshs: for jnt in joints: parentJnt = jnt.getParent() if parentJnt: # point에서 가장 가까운 Vertex의 Normal을 up으로 설정 pos = parentJnt.getTranslation( ws=True) vtx = getClosestVertexOnMesh( upMeshs[0], pos ) pos = vtx.getPosition() norm = vtx.getNormal() upPos = pos + norm * 1000000 # 노말 위치가 가까우면 방향이 틀어져 버림.. 그래서 큰 수를 곱함. upLoc = pm.spaceLocator(n='parentJnt_upLoc#') upLoc.t.set( upPos ) jntOrient( [parentJnt, jnt, upLoc] ) #pm.joint( parentJnt, edit=True, zso=True, oj='xyz', sao='yup' ) pm.delete( upLoc ) else: for jnt in joints: parentJnt = jnt.getParent() if parentJnt and parentJnt.type()=='joint': print jnt up = pm.spaceLocator() grandParent = parentJnt.getParent() if grandParent and grandParent.type()=='joint': pm.delete( pm.parentConstraint( grandParent, up ) ) else: pm.delete( pm.parentConstraint( parentJnt, up ) ) jntOrient( [parentJnt, jnt, up], worldUpType='objectrotation' ) pm.refresh() pm.select(jnt) pm.delete(up) # 끝 조인트 오리엔트 조정 if len(joints)>1: pm.joint( joints[-1], edit=True, oj='none' )
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 assignNewMaterialForSelected(objList=None, material="blinn"): """ Assign New Materials for Selected Objects """ if objList == None: objList = pm.filterExpand(sm=(10, 12)) for i in objList: shd, grp = createShader(material, "%s_SHD" % str(i)) assignShaderToObject(i, grp)
def preferred_joint_and_influence(meshes): """ Given a list of meshes. Cache joint influences and preferred joints cache_inf = {joint: influence} cache_pref = {mesh: (joint, joint, ...)} """ mesh_map = Geo_Cache() influence = dd(list) totals = dd(lambda: dd(dict)) for skin in (pmc.mel.findRelatedSkinCluster(a) for a in meshes): if skin: skin = pmc.PyNode(skin) joints = skin.getInfluence() # Get joints for jnt in joints: # Loop joints to get influences etc influences, weights = skin.getPointsAffectedByInfluence(jnt) for inf in influences: # A list for some reason... influence[jnt].append(inf) # Quick! Cache influence of joint mesh = inf.node() for vert, weight in zip(inf.indicesIter(), weights): # Loop our verts for face in mesh_map[mesh][vert]: totals[mesh][face][weight] = jnt sel = pmc.ls(sl=True) cache_inf = dict(pmc.select(b, r=True) or (a, tuple(pmc.PyNode(c) for c in pmc.filterExpand(ex=False, sm=31))) for a, b in influence.iteritems()) pmc.select(sel, r=True) cache_pref = dict((a, tuple(b[c][max(b[c])] for c in sorted(b))) for a, b in totals.iteritems()) return cache_inf, cache_pref
def removeMembersFromBevelSet(bevelSetName, edges=None): edges = edges if edges is not None else pm.filterExpand(sm=32, ex=True) bevelSetNode = pm.ls(bevelSetName, type='objectSet') if len(bevelSetNode) and (edges is not None): edges = [e for e in edges if e in bevelSetNode[0]] not len(edges) or bevelSetNode[0].removeMembers(edges) return bevelSetNode
def getFaceNormals(): faceList = [pm.MeshFace(res) for res in pm.filterExpand(expand = True, sm = 34)] if len(faceList) == 0: cmds.error("no faces selected!") norm = pm.dt.Vector() for face in faceList: norm += face.getNormal(space = 'world').normal() return norm.normal()
def nonQuad(*args): meshList = pm.ls(type='surfaceShape') if not meshList: return [] # Find Triangles pm.select(meshList) pm.polySelectConstraint(mode=3, type=0x0008, size=1) pm.polySelectConstraint(disable=True) tris = pm.filterExpand(ex=True, sm=34) or [] # Find N-Gons pm.select(meshList) pm.polySelectConstraint(mode=3, type=0x0008, size=3) pm.polySelectConstraint(disable=True) ngon = pm.filterExpand(ex=True, sm=34) or [] pm.select(cl=True) if tris or ngon: return True
def getSymSelection(): """If symmetry is on, edge loop's mirrored edges are also selected. However, user may WANT a cross-seam edge loop. Determine if this is the case by testing if selection is "along the seam", ie symSeam flag on filterExpand""" sel = getSelPolyEdges() if not sel: return # 32 masks edges, 31 masks verts - if there is anything along the seam, # assume user wants both sides and don't change selection if pmc.filterExpand(sel, sm=32, symSeam=True) or pmc.filterExpand( getConnectedCmpnts(sel, "Vertices"), sm=31, symSeam=True): return sel # nothing along seam: filterExpand to isolate "active" symmetry side pmc.select(pmc.filterExpand(sel, selectionMask=32, symActive=True)) # refresh selection with filter return getSelPolyEdges()
def getVertsFromSelection(cls, sel, *args, **kwargs): ''' retains current selection, returns vert list flattented ''' verts = pm.polyListComponentConversion(sel, tv=True) # pm.select(verts, r=True) # outVerts = pm.ls(sl=True, flatten=True) # pm.select(sel, r=True) outVerts = pm.filterExpand(verts, sm=31, ex=True) return outVerts
def uvmp_align_cardinal(*args, **kwargs): ''' automaticaly rotate uv shell to align selected edge vertically or horizontally ''' edges = pm.filterExpand(sm=32, ex=True) if edges: uvs = pm.polyListComponentConversion(edges[0], toUV=True) uvs = pm.filterExpand(uvs, sm=35, ex=True) uvA = pm.polyEditUV(uvs[0], q=True) uvB = pm.polyEditUV(uvs[1], q=True) pm.select(uvs, replace=True) xDiff = uvA[0] - uvB[0] yDiff = uvA[1] - uvB[1] angle = math.degrees(math.atan2(yDiff, xDiff)) # find the quadrant of the vector and flip the rotation if needed sign = 1 if angle <= 45 and angle > -180: sign = -1 # find the minimum angle while abs(angle) > 45: if angle > 0: angle = 90 - angle else: angle = 90 + angle angle = sign * angle # invert or not try: texDim = lcTexture.TextureEditor().getTextureDimensions() uvCenter = lcGeometry.UV().getBoundingBoxCenter() lcGeometry.UV().grabShell() lcGeometry.UV().rotate(angle, uvCenter, texDim) except: lcUtility.Utility.lc_print_exception('something went wrong') finally: pm.select(edges, replace=True) else: lcUtility.Utility.lc_print('Please select an edge to straighten along', mode='warning')
def createCollider(self, faces, name="collider_msh"): # Create Collider # Duplicate mesh meshCollider = pm.duplicate(faces[0].split(".")[0], name="collider_msh")[0] # Get same face in the duplicate mesh faces = pm.filterExpand([str(meshCollider) + "." + y.split(".")[1] for y in faces], sm=34) # Get all face in mesh faceMesh = pm.filterExpand(str(meshCollider) + ".f[*]", sm=34) # Reverse the face select faceReverse = list(set(faceMesh) - set(faces)) # Delete for the reverse face for keep face select pm.delete(faceReverse) return meshCollider
def insertEdgeLoop(weight=0.5, sma=3, splitType=1, div=1): """Mimics Insert Edge Loop in Maya, as it is used in the UI, and not how it works in MEL. """ edges = pm.filterExpand(expand=True, sm=32) for e in edges: e = pm.PyNode(e) pm.select(e, r=True) pm.polySelect(er=e.currentItemIndex()) pm.polySplitRing(weight=weight, fixQuads=1, splitType=splitType, sma=sma, div=div)
def selectSurface(self): listFace = pm.filterExpand(pm.ls(sl=1), sm=34) if listFace == None: listFace = [] listMesh = pm.ls(sl=1, type="transform") if len(listFace) > 0 and len(listMesh) > 0: self.printErr("Select face or mesh") return #MESH IS SELECT if len(listMesh) >= 1: if len(listMesh) > 1: self.printErr("Select only one mesh") return if len(listMesh[0].listRelatives(c=1, ni=1, s=1)) == 0: self.printErr("Select invalid mesh / only one shape") return self.surface = pm.filterExpand(str(listMesh[0]) + ".f[*]", sm=34) self.ui.surfaceInfo_le.setText("Mesh select -> {0}".format( listMesh[0])) self.IsFirstStart = True return #FACE IS SELECT if len(listFace) > 1: listFaceMesh = [] for x in listFace: if not str(x).split(".")[0] in listFaceMesh: listFaceMesh.append(str(x).split(".")[0]) if len(listFaceMesh) > 1: self.printErr("Select only one mesh") return self.surface = listFace self.ui.surfaceInfo_le.setText( "Face Select {0} in mesh {1}".format(len(listFace), listFaceMesh[0])) self.IsFirstStart = True return
def createCollider(self, faces, name="collider_msh"): # Create Collider #Duplicate mesh meshCollider = pm.duplicate(faces[0].split('.')[0], name="collider_msh")[0] #Get same face in the duplicate mesh faces = pm.filterExpand( [str(meshCollider) + "." + y.split(".")[1] for y in faces], sm=34) #Get all face in mesh faceMesh = pm.filterExpand(str(meshCollider) + ".f[*]", sm=34) #Reverse the face select faceReverse = list(set(faceMesh) - set(faces)) #Delete for the reverse face for keep face select pm.delete(faceReverse) return meshCollider
def selHardEdges(*args): meshList = pm.ls(type='surfaceShape') if not meshList: return [] # Find Triangles pm.select(meshList) pm.polySelectConstraint(mode=3, type=0x8000, sm=1) pm.polySelectConstraint(disable=True) hard = pm.filterExpand(ex=True, sm=32) or [] pm.select(hard) return 'select'
def selectSurface(self): listFace = pm.filterExpand(pm.ls(sl=1), sm=34) if listFace == None: listFace = [] listMesh = pm.ls(sl=1, type="transform") if len(listFace) > 0 and len(listMesh) > 0: self.printErr("Select face or mesh") return # MESH IS SELECT if len(listMesh) >= 1: if len(listMesh) > 1: self.printErr("Select only one mesh") return if len(listMesh[0].listRelatives(c=1, ni=1, s=1)) == 0: self.printErr("Select invalid mesh / only one shape") return self.surface = pm.filterExpand(str(listMesh[0]) + ".f[*]", sm=34) self.ui.surfaceInfo_le.setText("Mesh select -> {0}".format(listMesh[0])) self.IsFirstStart = True return # FACE IS SELECT if len(listFace) > 1: listFaceMesh = [] for x in listFace: if not str(x).split(".")[0] in listFaceMesh: listFaceMesh.append(str(x).split(".")[0]) if len(listFaceMesh) > 1: self.printErr("Select only one mesh") return self.surface = listFace self.ui.surfaceInfo_le.setText("Face Select {0} in mesh {1}".format(len(listFace), listFaceMesh[0])) self.IsFirstStart = True return
def noHoles(*args): meshList = pm.ls(type='surfaceShape') if not meshList: return [] # Find Triangles pm.select(meshList) pm.polySelectConstraint(mode=3, type=0x0008, h=1) pm.polySelectConstraint(disable=True) holes = pm.filterExpand(ex=True, sm=34) or [] pm.select(cl=True) if holes: return True
def uvmp_split_edges_at_UVs(*args, **kwargs): ''' automaticaly split edges wherever there is a uv border ''' sel = pm.ls(sl=True) if sel and pm.nodeType(sel[0]) == 'transform': polyObject = sel[0] pm.polyOptions(displayBorder=True, ao=True, sb=3) # get the open border uvs pm.select(polyObject.map, replace=True) pm.polySelectConstraint(t=0x0010, sh=0, bo=1, m=2) pm.polySelectConstraint(sh=0, bo=0, m=0) borderUVs = pm.ls(sl=True) borderEdges = pm.polyListComponentConversion(borderUVs, toEdge=True, internal=True) borderEdges = pm.filterExpand(borderEdges, sm=32, ex=True) for edge in borderEdges: if len(pm.PyNode(edge).connectedFaces()) < 2: print edge borderEdges.remove(edge) else: edgeUVs = pm.polyListComponentConversion(edge, toUV=True) edgeUVs = pm.filterExpand(edgeUVs, sm=35, ex=True) if not len(edgeUVs) > 2: borderEdges.remove(edge) print borderEdges pm.select(borderEdges, replace=True) pm.mel.eval('DetachEdgeComponent;') pm.delete(sel, constructionHistory=True) pm.select(sel, replace=True) else: lcUtility.Utility.lc_print('Please select an object', mode='warning')
def oppositeEdgesFromFaces(): """ Return 2 opposite edges from a face selection """ face_select = pm.selected() faces = pm.filterExpand(selectionMask = 34) ## Edge facesfromObject = faces[0].split('.')[0] final_edge_selection = [] for each in face_select: edges = each.getEdges() opposite_edges_index = edges[::2] opposite_edges = [] for index_edge in opposite_edges_index: edge_to_select = '{}.e[{}]'.format(facesfromObject,index_edge) opposite_edges.append(edge_to_select) final_edge_selection.append(opposite_edges) return(final_edge_selection)
def AlignVertex(self): print self.nv print self.a if not pm.selected(): return pm.runtime.ConvertSelectionToVertices(pm.selected(flatten=True)) vtxList = pm.filterExpand(selectionMask=31) vec = [v for v in AlignHelper.getVectors(vtxList)] for g in vec: moveVec = Vector_3D() ag = g - self.a moveVec = self.nv * (self.nv).inner(ag) moveVec = g - moveVec moveVec.name = g.name AlignHelper.moveVertex(moveVec)
def smoothMesh(target=None): if not target: target = s() polysOnly = py.filterExpand(target, sm=12) py.select(polysOnly, r=True) for i in range(0, len(target)): try: py.mel.eval( "polySmooth -mth 0 -dv 1 -bnr 2 -c 1 -kb 1 -ksb 1 -khe 0 -kt 1 -kmb 1 -suv 0 -peh 0 -sl 1 -dpe 1 -ps 0.1 -ro 1 -ch 1 " + target[i] + ";") py.mel.eval("BakeAllNonDefHistory;") py.mel.eval("bakePartialHistory -all;") except: print "Smooth failed; " + target[ i] + " probably isn't a polygonal mesh."
def addMembersIntoBevelSet(bevelSetName, edges=None): # TODO: Only the edges belong to the same mesh can be added. edges = edges if edges is not None else pm.filterExpand(sm=32, ex=True) bevelSetNode = pm.ls(bevelSetName, type='objectSet') if len(bevelSetNode) and (edges is not None): bevelSetNode[0].forceElement(edges) # forceElement doesn't always work. edges = edges if isinstance(edges[0], unicode) else [e.name() for e in edges] objestSetsContainingEdges = getObjectSetsContainingEdgesUsingAPI2( edges) objestSetsContainingEdges.discard(bevelSetNode[0].name()) for objectSet in objestSetsContainingEdges: objectSet = pm.ls(objectSet, type='objectSet')[0] intersection = bevelSetNode[0].getIntersection(objectSet) not len(intersection) or objectSet.removeMembers(intersection) return bevelSetNode
def attachToVertices(source, targetVertices=None): """Instances source, and attaches each instance to each vertice. If targetVertices == None, the selected vertices are used. """ if not targetVertices: targetVertices = pm.filterExpand(pm.ls(sl=True), expand=True, sm=31) else: if not hasattr("__next__", targetVertices): raise TypeError("targetVertices is not iterable.") for v in targetVertices: p = pm.pointPosition(v, w=True) target = pm.PyNode(v).node() attach(source, target, p)
def GetNormalVector(self): if not pm.selected(): pm.warning("Select 3 vertexes") return pm.runtime.ConvertSelectionToVertices(pm.selected(flatten=True)) vtxList = pm.filterExpand(selectionMask=31) if len(vtxList) < 3: pm.warning("Select 3 vertexes") return self.a = AlignHelper.getVector(vtxList[0]) b = AlignHelper.getVector(vtxList[1]) c = AlignHelper.getVector(vtxList[2]) ab = b - self.a ac = c - self.a self.nv = ab.outer(ac).getNormalizedVec() print self.nv print self.a
def bevelOnSelectedEdges( *args, **kwargs): dupMeshTransform = None edges, bevelSetName = args selectedMeshEdges = edges if len(edges) else pm.filterExpand(sm=32, ex=True) # Duplicate the mesh node. originMesh = pm.ls(selectedMeshEdges[0].name().partition('.')[0], type='mesh')[0] dupMeshTransform = utils.duplicateMeshTransform(bevelSetName) if len(dupMeshTransform): edgeIndices = utils.selectedEdgeindices(selectedMeshEdges) edges = [dupMeshTransform[0].e[i] for i in edgeIndices] if len(edges): with utils.MayaUndoChuck('bevelOnSelectedEdges'): bevelNode = pm.polyBevel3( edges, fraction=kwargs['fraction'], offsetAsFraction=kwargs['offsetAsFraction'], autoFit=kwargs['autoFit'], depth=kwargs['depth'], mitering=kwargs['mitering'], miterAlong=kwargs['miterAlong'], chamfer=kwargs['chamfer'], segments=kwargs['segments'], worldSpace=kwargs['worldSpace'], smoothingAngle=kwargs['smoothingAngle'], subdivideNgons=kwargs['subdivideNgons'], mergeVertices=kwargs['mergeVertices'], mergeVertexTolerance=kwargs['mergeVertexTolerance'], miteringAngle=kwargs['miteringAngle'], angleTolerance=kwargs['angleTolerance'], forceParallel=kwargs['forceParallel'], ch=kwargs['ch'] ) bevelNode[0].setName('MWBevelOnSelectedEdges#') return dupMeshTransform
def crvToJnt( curves=[], div=None, ep=True ): ''' update : 2015-04-29 ''' # args if curves: pm.selec(curves) curves = [pm.PyNode(c) for c in pm.filterExpand(sm=9) ] if not curves: raise node = curves[-1] nodeType = node.nodeType() transform = None crvShape = None if nodeType == 'nurbsCurve': crvShape = node transform = crvShape.getParent() elif nodeType == 'transform': transform = node crvShape = transform.getShapes( type='nurbsCurve' )[0] if div: rebCrv, rebuild = pm.rebuildCurve( crvShape, ch=True, rpo=False, rt=4, end=1, kr=0, kcp=0, kep=1, kt=0, s=4, d=3, tol=0.001 ) # curvature type transform = rebCrv crvShape = transform.getShapes( type='nurbsCurve' )[0] # 위치값 챙김. p=[] if div: if ep: for i in range(div+1): # 커브를 일정하게 나눈 위치 값을 가져옴 p.append( pm.pointOnCurve( crvShape, turnOnPercentage=True, parameter=(1.0/div)*i ) ) else: rebuild.rebuildType.set(0) # uniform rebuild.spans.set(div+1) for i in range( len( rebCrv.getCVs() ) ): p.append( crvShape.cv[i].getPosition() ) else: if ep: # editPoint의 위치값을 가져옴 for i in range( crvShape.numEPs() ): p.append( pm.xform( crvShape.ep[i], q=True, ws=True, t=True) ) else: # cv의 위치값을 가져옴 for i in range( len( crvShape.getCVs() ) ): p.append( crvShape.cv[i].getPosition() ) if div: pm.delete( transform ) JNTs = [] pm.select(cl=True) for pos in p: JNTs.append( pm.joint( p=pos) ) # 조인트 오리엔트 디폴트 pm.joint( JNTs[0], e=True, oj='xyz', secondaryAxisOrient='yup', ch=True, zso=True ) pm.select( JNTs ) return JNTs
def createShotSculptNode(): sel = pm.ls(sl=True) selSize = len(sel) ##Run error Checks if selSize < 1: pm.error("MS Shot-Sculptor: " + "no objects selected") for s in sel: if pm.filterExpand(sm=12, fp=True) == None: pm.error( "MS Shot-Sculptor: " + s + " is not a mesh object. Cannot create a Shot-Sculpt Group.", noContext=True) shapes = pm.listRelatives(s, shapes=True) if shapes == []: pm.error("MS Shot-Sculptor: " + s + "is not a Mesh object. Cannot add to Shot-Sculpt group.", noContext=True) ##get the name of the new node result = pm.promptDialog(title='create Shot Sculpt Node', message='Enter Name:', button=['OK', 'Cancel'], defaultButton='OK', cancelButton='Cancel', dismissString='Cancel') if result == 'OK': name = pm.promptDialog(q=True, t=True) ssn = pm.group(em=True, n=name + "_ShotSculpt") ##setup the SSnode for attr in [ 'tx', 'ty', 'tz', 'rx', 'ry', 'rz', 'sx', 'sy', 'sz', 'v' ]: channel = ssn + "." + attr pm.setAttr(channel, l=True, k=False, cb=False) pm.addAttr(ssn, longName="SSN_ID", k=False) pm.setAttr(ssn + ".SSN_ID", cb=False) ##store the influence objects and blendshapes pm.addAttr(longName="influenceObjs", dt="stringArray", k=False) pm.addAttr(longName="bshps", dt="stringArray", k=False) pm.addAttr(ssn, longName="envelope", at="float", hasMinValue=True, min=0, hasMaxValue=True, max=1, k=True, dv=1) selArray = [] BshpsArray = [] for i in range(selSize): ##add the selection to the array selArray.append(sel[i]) bshpName = sel[i] + "_" + ssn + "_bshp" ##create a blendshape pm.blendShape(sel[i], n=bshpName, foc=False) BshpsArray.append(bshpName) pm.connectAttr(ssn + ".envelope", BshpsArray[i] + ".envelope") pm.setAttr(ssn + '.influenceObjs', selArray) pm.setAttr(ssn + '.bshps', BshpsArray) #do UI stuff pm.textScrollList("SculptLayers_tsl", e=True, ra=True) setupMenu()
def createCurveFromEdge(name='spline_loca', step=1): sel = pm.selectedNodes() if len(sel) != 1: cmds.error('Trabaje en un objeto y sus edge') edges = pm.filterExpand(sm=32) if len(edges) == 1: cmds.error('Seleccione edges continuos') #Guardo el nombre del objeto nameObj = sel[0].split('|')[1] #Cantidad de edges cant = len(edges) infoVerts = [] fVerts = [] lVerts = [] #Recorro los edge y spliteo para conseguir el principio y final de cada edge for i in range(0, cant, step): infoVerts = pm.polyInfo(edges[i], ev=1) infoVerts = infoVerts[0].split(" ") fVerts.append(infoVerts[8]) lVerts.append(infoVerts[12]) #ordeno y compongo la seleccion de vertices vertexNum = [] [vertexNum.append(x) for x in fVerts + lVerts if x not in vertexNum] #si tiene step diferente a 1, agrego el primero y el ultimo if step != 1: if not fVerts in vertexNum: vertexNum.insert(-1, lVerts) if not lVerts in vertexNum: vertexNum.insert(0, fVerts) vertexSel = [] [vertexSel.append(nameObj + '.vtx[' + str(x) + ']') for x in vertexNum] #saco la posicion de cada vertice xOrig = mc.xform(vertexSel, q=True, ws=True, t=True) #Formateo las posicions de vertices origPts = zip(xOrig[0::3], xOrig[1::3], xOrig[2::3]) #Cuento la cantidad de puntos para la curva vertCount = len(vertexSel) #Creo la curva crv = mc.curve(n=name, p=origPts, degree=2) #Limpio la curva try: mc.rebuildCurve(crv, ch=False, rpo=True, rt=False, end=True, kr=False, kcp=False, kep=True, kt=True, s=vertCount, d=3, tol=0.01) mc.rebuildCurve(crv, ch=True, rpo=True, rt=False, end=True, kr=False, kcp=False, kep=True, kt=False, s=0, d=3, tol=0.01) except: pass return crv
def buildRivet(scale = 0.2): """ Creates a Rivet Between 2 edges Returns : - Rivet locator, - List of the 2 edge from curves nodes - Mesh Name """ if not (pm.pluginInfo('matrixNodes', q=True, loaded=True)): pm.loadPlugin( 'matrixNodes' ) _edges = pm.filterExpand(selectionMask = 32) ## Edge if len(_edges) < 2: pm.warning('n\Need 2 edges selected') elif len(_edges) > 2: pm.error('Too much edges selected! Only select 2!!') else: objectFromEdge = _edges[0].split('.')[0] edgeMaxNumber = pm.polyEvaluate(objectFromEdge, edge = True) objectShape = pm.PyNode(objectFromEdge).getShape() edgeCount = len(_edges) edgeNumber = [(edge.split('.e[')[1]).split(']')[0] for edge in _edges] ## RIVET LOC AND GRP SET UP rivet_grp= pm.group(em=True, name = '{}_rivet__grp__'.format(objectFromEdge)) rivet_locator = pm.spaceLocator(name = '{}_rivet'.format(objectFromEdge)) adb.changeColor_func(rivet_locator, 'index', col = 17) pm.PyNode(rivet_locator).localScaleX.set(scale) pm.PyNode(rivet_locator).localScaleY.set(scale) pm.PyNode(rivet_locator).localScaleZ.set(scale) pm.parent(rivet_locator, rivet_grp) _rivet_Attr = adbAttr.NodeAttr([rivet_locator]) _rivet_Attr.addAttr("edges_index", 'float2', nc=2) _rivet_Attr.addAttr("edge_index_0", int(edgeNumber[0]), min = 0, max = edgeMaxNumber, parent = "edges_index") _rivet_Attr.addAttr("edge_index_1", int(edgeNumber[1]), min = 0, max = edgeMaxNumber, parent = "edges_index") print _rivet_Attr _rivet_Attr.addAttr("UV", 'float2', nc=2) _rivet_Attr.addAttr("U_pos", 0.5, min = 0, max = 1, parent = "UV") _rivet_Attr.addAttr("V_pos", 0.5, min = 0, max = 1, parent = "UV") ## NODES CREATION curveFromEdge_nodes = [pm.createNode('curveFromMeshEdge', name = 'curveFromEdge_{}_{}'.format(objectFromEdge, x)) for x in edgeNumber] loft_node = pm.createNode('loft', name = 'rivet_loft__node__') pm.PyNode(loft_node).degree.set(1) pointOnSurface_node = pm.createNode('pointOnSurfaceInfo', name = 'pointOnSurface_node') pm.PyNode(pointOnSurface_node).turnOnPercentage.set(1) matrix_node = pm.createNode('fourByFourMatrix', name = 'mat__node__') decomposeMatrix_node = pm.createNode('decomposeMatrix', name = 'decompMat__node__') ## MAKING THE CONNECTIONS objectShape.worldMesh >> pm.PyNode(curveFromEdge_nodes[0]).inputMesh objectShape.worldMesh >> pm.PyNode(curveFromEdge_nodes[1]).inputMesh for index in range(0, edgeCount): pm.PyNode('{}.{}'.format(curveFromEdge_nodes[index], 'outputCurve')) >> pm.PyNode('{}.inputCurve[{}]'.format(loft_node, index)) loft_node.outputSurface >> pointOnSurface_node.inputSurface rivet_locator.U_pos >> pointOnSurface_node.parameterU rivet_locator.V_pos >> pointOnSurface_node.parameterV pos_node_attr = ['normal', 'tangentU.tangentU', 'tangentV.tangentV', 'position.position'] xyz = 'XYZ' for i in range(len(pos_node_attr)): for j in range(3): axe = xyz[j] if 'tU' in pos_node_attr[i]: axe = axe.lower() elif 'tV' in pos_node_attr[i]: axe = axe.lower() pm.PyNode('{}.{}{}'.format(pointOnSurface_node, pos_node_attr[i], axe)) >> pm.PyNode('{}.in{}{}'.format(matrix_node, i, j)) matrix_node.output >> decomposeMatrix_node.inputMatrix for i in range(3): axe = xyz[i] pm.PyNode('{}.outputRotate{}'.format(decomposeMatrix_node, axe)) >> pm.PyNode('{}.rotate{}'.format(rivet_grp, axe)) pm.PyNode('{}.outputTranslate{}'.format(decomposeMatrix_node, axe)) >> pm.PyNode('{}.translate{}'.format(rivet_grp, axe)) rivet_locator.edge_index_0 >> curveFromEdge_nodes[0].edgeIndex[0] rivet_locator.edge_index_1 >> curveFromEdge_nodes[1].edgeIndex[0] sys.stdout.write('// Result: Rivet created! // \n') return rivet_locator, curveFromEdge_nodes, objectFromEdge
def prebuild(self): mesh_to_follow_list = pmc.ls(self.model.mesh_to_follow) if not mesh_to_follow_list: pmc.error("for module \"{0}\", no mesh given, need one to attach the ctrls".format(self.model.module_name)) return False elif len(mesh_to_follow_list) > 1: pmc.error("for module \"{0}\", multiple objects match given name, give the long_name of the object to find the chosen one".format(self.model.module_name)) return False elif mesh_to_follow_list[0].getShape() is None or pmc.nodeType(mesh_to_follow_list[0].getShape()) != "mesh": pmc.error("for module \"{0}\", given object isn't a mesh".format(self.model.module_name)) return False else: self.mesh_to_follow = mesh_to_follow_list[0] if self.model.top_creation_switch: top_components_vertex_list = pmc.filterExpand(pmc.ls(self.model.top_selection), sm=31) top_components_edge_list = pmc.filterExpand(pmc.ls(self.model.top_selection), sm=32) top_components_face_list = pmc.filterExpand(pmc.ls(self.model.top_selection), sm=34) if not top_components_vertex_list and not top_components_edge_list and not top_components_face_list: pmc.error("for module \"{0}\", no components given in top selection".format(self.model.module_name)) return False elif top_components_vertex_list is not None and (top_components_edge_list is not None or top_components_face_list is not None) or \ (top_components_edge_list is not None and top_components_face_list is not None): pmc.error("for module \"{0}\", more than one component's type given in top selection".format(self.model.module_name)) return False elif (top_components_vertex_list is not None and len(top_components_vertex_list) != len(self.model.top_selection)) or \ (top_components_edge_list is not None and len(top_components_edge_list) != len(self.model.top_selection)) or \ (top_components_face_list is not None and len(top_components_face_list) != len(self.model.top_selection)): pmc.error("for module \"{0}\", non-component type object given in top selection, need components only".format(self.model.module_name)) return False elif (top_components_vertex_list is not None and len(top_components_vertex_list) == 1) or \ (top_components_edge_list is not None and len(top_components_edge_list) == 1) or \ (top_components_face_list is not None and len(top_components_face_list) == 1): pmc.error("for module \"{0}\", only one component given in top selection, need at least 2".format(self.model.module_name)) return False elif top_components_vertex_list is not None: self.top_components = pmc.ls(self.model.top_selection) self.top_components_type = "vertex" elif top_components_edge_list is not None: self.top_components = pmc.ls(self.model.top_selection) self.top_components_type = "edge" elif top_components_face_list is not None: self.top_components = pmc.ls(self.model.top_selection) self.top_components_type = "face" if self.model.bot_creation_switch: bot_components_vertex_list = pmc.filterExpand(pmc.ls(self.model.bot_selection), sm=31) bot_components_edge_list = pmc.filterExpand(pmc.ls(self.model.bot_selection), sm=32) bot_components_face_list = pmc.filterExpand(pmc.ls(self.model.bot_selection), sm=34) if not bot_components_vertex_list and not bot_components_edge_list and not bot_components_face_list: pmc.error("for module \"{0}\", no components given in bot selection".format(self.model.module_name)) return False elif bot_components_vertex_list is not None and (bot_components_edge_list is not None or bot_components_face_list is not None) or \ (bot_components_edge_list is not None and bot_components_face_list is not None): pmc.error("for module \"{0}\", more than one component's type given in bot selection".format(self.model.module_name)) return False elif (bot_components_vertex_list is not None and len(bot_components_vertex_list) != len(self.model.bot_selection)) or \ (bot_components_edge_list is not None and len(bot_components_edge_list) != len(self.model.bot_selection)) or \ (bot_components_face_list is not None and len(bot_components_face_list) != len(self.model.bot_selection)): pmc.error("for module \"{0}\", non-component type object given in bot selection, need components only".format(self.model.module_name)) return False elif (bot_components_vertex_list is not None and len(bot_components_vertex_list) == 1) or \ (bot_components_edge_list is not None and len(bot_components_edge_list) == 1) or \ (bot_components_face_list is not None and len(bot_components_face_list) == 1): pmc.error("for module \"{0}\", only one component given in bot selection, need at least 2".format(self.model.module_name)) return False elif bot_components_vertex_list is not None: self.bot_components = pmc.ls(self.model.bot_selection) self.bot_components_type = "vertex" elif bot_components_edge_list is not None: self.bot_components = pmc.ls(self.model.bot_selection) self.bot_components_type = "edge" elif bot_components_face_list is not None: self.bot_components = pmc.ls(self.model.bot_selection) self.bot_components_type = "face" self.view.refresh_view() pmc.select(cl=1) return True
def selectedEdgeindices(edges=[]): edges = edges if edges else pm.filterExpand(sm=32, ex=True) return [ int(e.name().partition('[')[2].partition(']')[0]) for e in pm.ls(edges, flatten=True) ]
def jointsSetup(self): self.all_locs = [] self.all_joint = [] for each in self.all_guide: _joint = pm.joint(n=each.name().replace('guide', 'jnt__')) _loc = pm.spaceLocator(n=each.name().replace('guide', 'loc__')) pm.PyNode(_loc).getShape().localScaleX.set(0.2) pm.PyNode(_loc).getShape().localScaleY.set(0.2) pm.PyNode(_loc).getShape().localScaleZ.set(0.2) adb.changeColor_func(_loc, 'index', 14) pm.parent(_joint, w=True) self.all_joint.append(_joint) self.all_locs.append(_loc) for joint, guide in zip(self.all_joint, self.all_guide): pm.matchTransform(joint, guide, pos=True) pm.parent(joint, guide) for loc, guide in zip(self.all_locs, self.all_guide): pm.matchTransform(loc, guide, pos=True) pm.parentConstraint(guide, loc) pm.select(None) ## SCALING scaling_grp = pm.group(em=True, n='scaling__grp__') pm.parent('l__arm_clav__guide__root__grp__', 'l__arm_elbow__guide__root__grp__', 'l__arm_hand__guide__root__grp__', 'l__leg_main__guide__root__grp__', 'r__arm_clav__guide__root__grp__', 'r__arm_elbow__guide__root__grp__', 'r__arm_hand__guide__root__grp__', 'r__leg_main__guide__root__grp__', 'spine_guide__curve', scaling_grp) pm.PyNode(scaling_grp).setScale((0.05, 0.05, 0.05)) pm.parent(w=True) pm.delete(scaling_grp) ## ----------------------------------------------- ## SPINE SUITE pm.select(self.spine_curve, r=True) sel = pm.select(".cv[*]") cvs = pm.filterExpand(fullPath=True, sm=28) # Nombre de vertex sur la curve # nbCvs = len(cvs) oCollClusters = [pm.cluster(cvs[x]) for x in range(0, nbCvs)] self.all_spine_guide = [] for clus in oCollClusters: clus[1].v.set(0) spine_guide = pm.sphere(n='m__spine__guide_01', r=0.05)[0] self.all_spine_guide.append(spine_guide) pm.matchTransform(spine_guide, clus, pos=True) for oClus, spine in zip(oCollClusters, self.all_spine_guide): pm.parentConstraint(spine, oClus) for spine_guide in self.all_spine_guide: pm.select(spine_guide) mc.FreezeTransformations() pm.PyNode(self.all_spine_guide[1]).v.set(0) pm.PyNode(self.all_spine_guide[-2]).v.set(0) cluster_grp = pm.group(oCollClusters, n='spine_cls__grp__', w=1) all_spine_guide_grp = pm.group(self.all_spine_guide, n='spine_guide__grp__', w=1) self.all_guide.extend(self.all_spine_guide) ## Hide loc self.locs_grp = pm.group(n='x__locs_pos__grp__') pm.parent(self.all_locs, self.locs_grp) pm.PyNode(self.locs_grp).v.set(0) ## associate shader spine_shader = pm.shadingNode('lambert', asShader=True, n='yellow_guide_shader') pm.setAttr(spine_shader + ".incandescence", 0, 0.42, 0.06, type='double3') pm.select(pm.ls(type='nurbsSurface')) for spine_guide in pm.selected(): pm.select(spine_guide) pm.hyperShade(assign=spine_shader) @changeColor('index', col=(14)) def create_curve(): _curve_arm_1 = pm.curve(p=[(2.2, 5, -0.05), (1.45, 5, -0.05)], k=[0, 1], d=1) _curve_arm_2 = pm.curve(p=[(1.45, 5, -0.05), (0.5, 5, 0)], k=[0, 1], d=1) _curve_arm_4 = pm.curve(p=[(-2.2, 5, -0.05), (-1.45, 5, -0.05)], k=[0, 1], d=1) _curve_arm_5 = pm.curve(p=[(-1.45, 5, -0.05), (-0.5, 5, 0)], k=[0, 1], d=1) r_leg_thigh_curve = pm.curve(p=[(-0.4, 3.2, 0.05), (-0.4, 1.75, 0.185)], k=[0, 1], d=1) l_leg_thigh_curve = pm.curve(p=[(0.4, 3.2, 0.05), (0.4, 1.75, 0.185)], k=[0, 1], d=1) r_leg_knee_curve = pm.curve(p=[(-0.4, 1.75, 0.185), (-0.4, 0.35, 0)], k=[0, 1], d=1) l_leg_knee_curve = pm.curve(p=[(0.4, 1.75, 0.185), (0.4, 0.35, 0)], k=[0, 1], d=1) all_curves = [ _curve_arm_1, _curve_arm_2, _curve_arm_4, _curve_arm_5, r_leg_thigh_curve, l_leg_thigh_curve, r_leg_knee_curve, l_leg_knee_curve ] self.curves_grp = pm.group(em=True, n='x__curves__grp__', w=True) pm.select(self.all_joint, r=True) pm.select(all_curves, add=True) mc.SmoothBindSkin() pm.parent(_curve_arm_1, _curve_arm_2, _curve_arm_4, _curve_arm_5, r_leg_thigh_curve, l_leg_thigh_curve, r_leg_knee_curve, l_leg_knee_curve, self.spine_curve, cluster_grp, self.curves_grp) return self.curves_grp create_curve() guide_scale_grp = pm.group(em=True, n='x__guide__grp__') pm.parent('l__arm_clav__guide__root__grp__', 'l__arm_elbow__guide__root__grp__', 'l__arm_hand__guide__root__grp__', 'l__leg_main__guide__root__grp__', 'r__arm_clav__guide__root__grp__', 'r__arm_elbow__guide__root__grp__', 'r__arm_hand__guide__root__grp__', 'r__leg_main__guide__root__grp__', 'spine_guide__grp__', guide_scale_grp) return guide_scale_grp
def AlignVertexOnCircle(axis,mode,sp): space=['object','world'][sp] if not pm.selected(): return pm.runtime.ConvertSelectionToVertices(pm.selected(flatten=True)) vtxList = pm.filterExpand(selectionMask=31) if len(vtxList)<3: return if axis == 0: posY = [pm.PyNode(p).getPosition(space=space)[1] for p in vtxList] posZ = [pm.PyNode(p).getPosition(space=space)[2] for p in vtxList] cenYZ = [(max(posY) + min(posY))/2, (max(posZ) + min(posZ))/2] length = [sqrt(pow(y-cenYZ[0],2) + pow(z-cenYZ[1],2)) for (y,z) in zip(posY,posZ)] if mode==0: r=min(length) if mode==1: r = (max(length) + min(length))/2 if mode==2: r = max(length) sinCos = [[(y-cenYZ[0])/l,(z-cenYZ[1])/l] for (y,z,l) in zip(posY,posZ,length)] for (vtx,rad) in zip(vtxList,sinCos): valueY = cenYZ[0] + r*rad[0] valueZ = cenYZ[1] + r*rad[1] if space=='object': pm.move(valueY,vtx,moveY=True,objectSpace=True) pm.move(valueZ,vtx,moveZ=True,objectSpace=True) else: pm.move(valueY,vtx,moveY=True) pm.move(valueZ,vtx,moveZ=True) if axis == 1: posX = [pm.PyNode(p).getPosition(space=space)[0] for p in vtxList] posZ = [pm.PyNode(p).getPosition(space=space)[2] for p in vtxList] cenXZ = [(max(posX) + min(posX))/2, (max(posZ) + min(posZ))/2] length = [sqrt(pow(x-cenXZ[0],2) + pow(z-cenXZ[1],2)) for (x,z) in zip(posX,posZ)] if mode==0: r=min(length) if mode==1: r = (max(length) + min(length))/2 if mode==2: r = max(length) sinCos = [[(x-cenXZ[0])/l,(z-cenXZ[1])/l] for (x,z,l) in zip(posX,posZ,length)] for (vtx,rad) in zip(vtxList,sinCos): valueX = cenXZ[0] + r*rad[0] valueZ = cenXZ[1] + r*rad[1] if space=='object': pm.move(valueX,vtx,moveX=True,objectSpace=True) pm.move(valueZ,vtx,moveZ=True,objectSpace=True) else: pm.move(valueX,vtx,moveX=True) pm.move(valueZ,vtx,moveZ=True) if axis == 2: posX = [pm.PyNode(p).getPosition(space=space)[0] for p in vtxList] posY = [pm.PyNode(p).getPosition(space=space)[1] for p in vtxList] cenXY = [(max(posX) + min(posX))/2, (max(posY) + min(posY))/2] length = [sqrt(pow(x-cenXY[0],2) + pow(y-cenXY[1],2)) for (x,y) in zip(posX,posY)] if mode==0: r=min(length) if mode==1: r = (max(length) + min(length))/2 if mode==2: r = max(length) sinCos = [[(x-cenXY[0])/l,(y-cenXY[1])/l] for (x,y,l) in zip(posX,posY,length)] for (vtx,rad) in zip(vtxList,sinCos): valueX = cenXY[0] + r*rad[0] valueY = cenXY[1] + r*rad[1] if space=='object': pm.move(valueX,vtx,moveX=True,objectSpace=True) pm.move(valueY,vtx,moveY=True,objectSpace=True) else: pm.move(valueX,vtx,moveX=True) pm.move(valueY,vtx,moveY=True)
def __init__(self, *args, **kwargs): if args: pm.select(args) curves = pm.filterExpand( sm=9, expand=True ) # Nurbs Curves cps = pm.filterExpand( sm=39, expand=True ) # Curve Parameter Points eps = pm.filterExpand( sm=30, expand=True ) # Edit Points cvs = pm.filterExpand( sm=28, expand=True ) # Control Vertices (CVs) knots = pm.filterExpand( sm=40, expand=True ) # Curve Knot #print args #print curves, cps, eps, cvs, knots # Nurbs Curves if curves: self.curve = pm.PyNode( curves[0] ) self.param = kwargs.get( 'parameter', kwargs.get( 'p', 0.5)) # Curve Parameter Points if cps: curveStr, paramStr = cps[0].split('.u[') self.curve = pm.PyNode( curveStr ) self.param = float( paramStr[:-1] ) # Edit Points if eps: # 커브쉐입 이름 가져옴 curve = pm.PyNode( eps[0].split('.ep[')[0] ) epNum = int( eps[0].split('.ep[')[1][:-1] ) # 이름에서 순서만 따옴. # # knotValue들이 parameter값들로 추정됨. # # knotValue( parameter )값 가져옴. # degree가 1일경우엔 : editPoint의순서와 knotValue의 순서가 1:1로 매핑됨. # 2이상일경우 : editPoint degree-1부터 -(degree-1) # degree = curve.degree() # degree knotValues = curve.getKnots() if not degree == 1: knotValues = knotValues[ degree-1 : -(degree-1) ] # degree가 1이면 어레이 조정 param = knotValues[ epNum ] self.curve = curve self.param = param #print self.curve, self.param self.name = kwargs.get( 'name', kwargs.get( 'n', 'xformOnCrv#')) self.turnOnPercentage= kwargs.get( 'turnOnPercentage', kwargs.get( 'top', False)) self.locatorShape = kwargs.get( 'locatorShape', kwargs.get( 'shape', 'locator')) # locator, group 중 하나 self.vectorShape ='group' # locator, group 중 하나 # # 로케이터 회전 형식 : None, aim, orient 중하나 # self.rotate = kwargs.get( 'rotate', kwargs.get( 'r', None)) # 로케이터 aim축 : x, y, z, -x, -y, -z, vector 중 하나 self.aimVector = self._strToVec( kwargs.get( 'aimVector', kwargs.get( 'aim', 'x')) ) # 로케이터 up축 : x, y, z, -x, -y, -z, vector 중 하나 self.upVector = self._strToVec( kwargs.get( 'upVector', kwargs.get( 'up', 'y')) ) # 로케이터 aim축 대상 : tangent, normal, vector, object 중 하나 self.worldAimType = kwargs.get( 'worldAimType', kwargs.get( 'waimt', 'tangent')) # 로케이터 up축 대상: tangent, normal, scene, vector, object, objectrotation, curverotation 중 하나 self.worldUpType = kwargs.get( 'worldUpType', kwargs.get( 'wupt', 'curverotation')) self.worldAimVector = self._strToVec( kwargs.get( 'worldAimVector', kwargs.get( 'waim', 'x')) ) # x, y, z, -x, -y, -z, vector 중 하나, worldAimType 이 scene, vector 일때만 유효. self.worldUpVector = self._strToVec( kwargs.get( 'worldUpVector', kwargs.get( 'wup', 'y')) ) # x, y, z, -x, -y, -z, vector 중 하나, worldUpType 이 scene, vector 일때만 유효. self.worldAimObject = kwargs.get( 'aimObject', kwargs.get( 'wao', None)) # worldAimType 이 object, objectrotation 일때만 유효. self.worldUpObject = kwargs.get( 'worldUpObject', kwargs.get( 'wuo', None)) # worldUpType 이 object, objectrotation 일때만 유효. self.create()
def edgeToJnt( edges=None, reverse=False, dispCV=False, dispAxis=False, createCurve=False): ''' update : 2015-04-27 ''' if not edges: edges = pm.filterExpand( sm=32 ) if not edges: raise # recast # edges = [ pm.PyNode(edge) for edge in edges ] # 이렇게 하면 파이멜이 엣지를 제대로 처리 못함 선택한걸로 해야 할듯 pm.select(edges) edges = pm.selected() # 엣지 이름에서 폴리곤 이름 알아옴 mesh = pm.PyNode( edges[0].name().split('.')[0] ) # 폴리곤에서 커브 추출 crvFromPoly = pm.polyToCurve( form=0, degree=1, ch=False )[0] curve = pm.PyNode( crvFromPoly ) curve.dispCV.set(dispCV) # cv좌표 얻어옴. points = curve.getCVs() # 좌표에 조인트 생성 pm.select(cl=True) jnts = [] for point in points: jnt = pm.joint( p=point ) jnt.displayLocalAxis.set( dispAxis ) jnts.append( jnt ) # 뒤집기 if reverse: # 조인트 뒤집음 pm.select( jnts[-1] ) pm.mel.RerootSkeleton() pm.reverseCurve( curve, replaceOriginal=True, ch=False ) jnts.reverse() # 조인트 오리엔트 조정 for jnt in jnts: parentJnt = jnt.getParent() if parentJnt: # point에서 가장 가까운 Vertex의 Normal을 up으로 설정 pos = parentJnt.getTranslation( ws=True) vtx = getClosestVertexOnMesh( mesh, pos ) pos = vtx.getPosition( space='world' ) norm = vtx.getNormal() upPos = pos + norm upLoc = pm.spaceLocator(n='parentJnt_upLoc#') upLoc.t.set( upPos ) jntOrient( [parentJnt, jnt, upLoc], aimAxis='x', worldAimVector='x', upAxis='y', worldUpVector='y' ) #pm.joint( parentJnt, edit=True, zso=True, oj='xyz', sao='yup' ) pm.delete( upLoc ) # 버텍스의 위치를 확인하고 싶으면 이 구문을 주석 처리할것 pm.select( jnt ) # 끝 조인트 오리엔트 조정 pm.joint( jnts[-1], edit=True, oj='none' ) if not createCurve: pm.delete( curve ) return jnts
def makeCurvesDynamic( nodes=[], prefix='' ): ''' update : 2015-05-08 # # 마야에서 기본으로 같은 기능을 하는 MakeCurvesDynamic 스크립트가 있으나 # 리턴 값이 없어 사용이 불가 # pm.runtime.MakeCurvesDynamic('curve1') # # makeCurvesDynamic 2 { "0", "1", "0", "1", "0"}; # $args[0] = surfaceAttach If true then connect the hairs to a surface(also selected) basing the uv on the nearest point to the first curve cv # $args[1] = snapToSurface If true and attaching to a surface then also snap the curve to the surface. # $args[2] = matchPosition If true then make the input curve a degree one so resulting output curve exactly matches the position. # $args[3] = createOutCurves If true then output curves are created # $args[4] = createPfxHair If true then hair is created. # ''' # ========================================= # # 입력 # # ========================================= if nodes: pm.select(nodes) # args curves = [] curves = [pm.PyNode(c) for c in pm.filterExpand(sm=9) ] if not curves: raise # get hairSystem hairSystem=None hairSystems = pm.ls(sl=True, dag=True, type='hairSystem') if hairSystems: hairSystem = hairSystems[-1] # get nucleus nucleus=None nucleuss = pm.ls(sl=True, dag=True, type='nucleus') if nucleuss: nucleus = nucleuss[-1] # ========================================= # # 생성 # # ========================================= # # 노드생성(1/4) : nucleus # if not nucleus and not hairSystem: nucleus = pm.createNode( 'nucleus' ) nucleus.rename( prefix+'_nucleus' ) pm.PyNode('time1').outTime >> nucleus.currentTime # # 노드생성(2/4) : hairSystem # hairSystemTr = None if hairSystem: hairSystemTr = hairSystem.getParent() else: hairSystem = pm.createNode( 'hairSystem' ) hairSystemTr = hairSystem.getParent() hairSystemTr.rename( prefix+'_hairSys' ) # 새로 생성된 헤어와 뉴클리어스 연결 << connectAttr nextAvailable플래그로 해결해보려했으나.. 복잡.. 아래처럼 멜을 사용하는게 제일 편함. #pm.PyNode('time1').outTime >> hairSystem.currentTime #hairSystem.currentState >> nucleus.inputActive[0] #hairSystem.startState >> nucleus.inputActiveStart[0] #nucleus.outputObjects[0] >> hairSystem.nextState #nucleus.startFrame >> hairSystem.startFrame # 새로 생성된 헤어와 뉴클리어스 연결 pm.mel.assignNSolver( nucleus ) # default Value hairSystem.active.set( True ) # # 노드생성(3/4) : follicle 생성 # follicle = pm.createNode( 'follicle' ) follicleTr = follicle.getParent() follicleTr.rename( prefix+'_follicle' ) # 기본값 follicle.restPose.set(1) # same as start follicle.startDirection.set(1) # start Curve base follicle.degree.set(2) follicle.clumpWidth.set(5) # 폴리클 디스플레이 크기 # # 노드생성(4/4) : curve Setting # # startCurve 생성 startCurve = curves[-1] startCurve.setParent( follicleTr ) startCurve.rename( prefix+'_startCurve' ) # outputCurve 생성 outputCurveShape = pm.createNode( 'nurbsCurve' ) outputCurve = outputCurveShape.getParent() outputCurve.rename( prefix+'_outputCurve' ) # ========================================= # # 연결 # # ========================================= settableNum = 0 while True: if hairSystem.inputHair[ settableNum ].isSettable(): break settableNum +=1 startCurve.getShape().worldSpace >> follicle.startPosition follicle.outHair >> hairSystem.inputHair[ settableNum ] hairSystem.outputHair[ settableNum ] >> follicle.currentPosition pm.connectAttr( follicle+'.outCurve', outputCurveShape+'.create' ) # follicle.outCurve >> outputCurveShape.create # 이부분에서 다음 경고 발생: Warning: pymel.core.general : Could not create desired MFn. Defaulting to MFnDagNode. # # ========================================= # # 리턴 # # ========================================= return outputCurve, follicle, hairSystem, nucleus
def crvToJnt( objs=[], div=None, ep=True ): ''' update : 2015-04-27 curve, upMesh 순으로 선택하고 실행 div 를 명시하면 일정간격의 조인트를 얻음. import rig.joint as jnt jnt.crvToJnt() jnt.crvToJnt(ep=False) # 해당 없음. 커브 cv 위치에 조인트가 생김 jnt.crvToJnt(div=10) jnt.crvToJnt(ep=True) # 해당 없음. 커브 ep 위치에 조인트가 생김 jnt.crvToJnt(ep=False) # 해당 없음. 커브 cv 위치에 조인트가 생김 jnt.crvToJnt(div=10, ep=True) # 해당 없음. 커브 cv 위치에 조인트가 생김 jnt.crvToJnt(div=10, ep=False) # 해당 없음. 커브 cv 위치에 조인트가 생김 ''' # args if objs: pm.selec(objs) objs = pm.selected() if not objs: raise curves = [pm.PyNode(c) for c in pm.filterExpand(sm=9) ] if not curves: raise upMeshs = [] if pm.filterExpand(sm=12): upMeshs = [pm.PyNode(c) for c in pm.filterExpand(sm=12) ] # 업축으로 사용할 메쉬 node = curves[-1] nodeType = node.nodeType() #cv = True #ep = True transform = None crvShape = None if nodeType == 'nurbsCurve': crvShape = node transform = crvShape.getParent() elif nodeType == 'transform': transform = node crvShape = transform.getShapes( type='nurbsCurve' )[0] if div: rebCrv, rebuild = pm.rebuildCurve( crvShape, ch=True, rpo=False, rt=4, end=1, kr=0, kcp=0, kep=1, kt=0, s=4, d=3, tol=0.001 ) # curvature type transform = rebCrv crvShape = transform.getShapes( type='nurbsCurve' )[0] # 위치값 챙김. p=[] if div: if ep: for i in range(div+1): # 커브를 일정하게 나눈 위치 값을 가져옴 p.append( pm.pointOnCurve( crvShape, turnOnPercentage=True, parameter=(1.0/div)*i ) ) else: rebuild.rebuildType.set(0) # uniform rebuild.spans.set(div+1) for i in range( len( rebCrv.getCVs() ) ): p.append( crvShape.cv[i].getPosition() ) else: if ep: # editPoint의 위치값을 가져옴 for i in range( crvShape.numEPs() ): p.append( pm.xform( crvShape.ep[i], q=True, ws=True, t=True) ) else: # cv의 위치값을 가져옴 for i in range( len( crvShape.getCVs() ) ): p.append( crvShape.cv[i].getPosition() ) if div: pm.delete( transform ) JNTs = [] pm.select(cl=True) for pos in p: JNTs.append( pm.joint( p=pos) ) # 조인트 오리엔트 조정: 메쉬의 가장 가까운 점의 노말을 조인트의 up으로 설정 if upMeshs: for jnt in JNTs: parentJnt = jnt.getParent() if parentJnt: # point에서 가장 가까운 Vertex의 Normal을 up으로 설정 pos = parentJnt.getTranslation( ws=True) vtx = getClosestVertexOnMesh( upMeshs[0], pos ) pos = vtx.getPosition() norm = vtx.getNormal() upPos = pos + norm * 1000000 # 노말 위치가 가까우면 방향이 틀어져 버림.. 그래서 큰 수를 곱함. upLoc = pm.spaceLocator(n='parentJnt_upLoc#') upLoc.t.set( upPos ) jntOrient( [parentJnt, jnt, upLoc] ) #pm.joint( parentJnt, edit=True, zso=True, oj='xyz', sao='yup' ) pm.delete( upLoc ) else: for jnt in JNTs: parentJnt = jnt.getParent() if parentJnt: up = pm.spaceLocator() grandParent = parentJnt.getParent() if grandParent: pm.delete( pm.parentConstraint( grandParent, up ) ) else: pm.delete( pm.parentConstraint( parentJnt, up ) ) jntOrient( [parentJnt, jnt, up], worldUpType='objectrotation' ) pm.refresh() pm.select(jnt) pm.delete(up) # 끝 조인트 오리엔트 조정 pm.joint( JNTs[-1], edit=True, oj='none' ) pm.select( JNTs ) return JNTs