Created
December 8, 2021 07:30
-
-
Save zclongpop123/f16f1e52a780e39fb1603bdf5bb556a7 to your computer and use it in GitHub Desktop.
Smooth绑定模型
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from maya import cmds,mel | |
import maya.api.OpenMaya as om | |
import maya.api.OpenMayaAnim as oma | |
# info | |
# only use for Catmull-Clark subdivision !!!! | |
# make sure both mesh was bound to the same skeleton !!!! | |
# step 1. select source mesh | |
# step 2. select smooth mesh | |
# step 3. run script | |
# create by jmelon 2019/11/30 | |
# have fun :) | |
def convert_str_to_depend_node(name): | |
selection_list = om.MGlobal.getSelectionListByName(name) | |
return selection_list.getDependNode(0) | |
def convert_str_to_Component(name): | |
selection_list = om.MGlobal.getSelectionListByName(name) | |
return selection_list.getComponent(0) | |
def getSkinCluster(mesh): | |
skin_cluster = mel.eval('findRelatedSkinCluster("{}")'.format(mesh)) | |
if skin_cluster: | |
return skin_cluster, convert_str_to_depend_node(skin_cluster) | |
def GetWeightMap(shape, skin, pCount): | |
comp = convert_str_to_Component(shape.fullPathName()) | |
jointCount = len(skin.influenceObjects()) | |
weightMap = list() | |
weights = skin.getWeights(comp[0], comp[1])[0] | |
for i in range(0, pCount* jointCount, jointCount): | |
weightMap.append( [i for i in weights[i:i+ jointCount] ] ) | |
return weightMap | |
#---------------- | |
def GetEdgeFacesMap(mesh): | |
edgeIter = om.MItMeshEdge(mesh) | |
edgeFaces = list() | |
while not edgeIter.isDone(): | |
edgeFaces.append(edgeIter.getConnectedFaces()) | |
edgeIter.next() | |
return edgeFaces | |
def GetVertexEdgesMap(mesh): | |
vIter = om.MItMeshVertex(mesh) | |
vertexEdges = list() | |
while not vIter.isDone(): | |
vertexEdges.append(vIter.getConnectedEdges()) | |
vIter.next() | |
return vertexEdges | |
def GetFaceVertexMap(Mesh): | |
fIter = om.MItMeshPolygon(Mesh) | |
faceVertices = list() | |
while not fIter.isDone(): | |
faceVertices.append(fIter.getVertices()) | |
fIter.next(1) | |
return faceVertices | |
def GetVertexVertices(mesh): | |
vIter = om.MItMeshVertex(mesh) | |
vv = list() | |
while not vIter.isDone(): | |
vv.append( vIter.getConnectedVertices() ) | |
vIter.next() | |
return vv | |
def GetVertexAroundVertices(mesh, fvRel): | |
vIter = om.MItMeshVertex(mesh) | |
vv = list() | |
va = list() | |
while not vIter.isDone(): | |
vv.append( vIter.getConnectedVertices() ) | |
vt = list() | |
fArray = vIter.getConnectedFaces() | |
for face in fArray: | |
vt += fvRel[face] | |
t = set(vt)- set(vv[-1]) | |
t.remove(vIter.index()) | |
va.append( list( t) ) | |
vIter.next() | |
return [vv, va ] | |
# #------------------- | |
def FindEdgeFromPoints(points, edgeRel): | |
edge0 = edgeRel[points[0]] | |
edge1 = edgeRel[points[1]] | |
isc = set(edge0)&set(edge1) | |
if len(isc) == 1: | |
return list(isc)[0] | |
else: | |
print "error" | |
return False | |
def FindAroundPoints(points, vRel, bound): | |
ap = list() | |
for point in points: | |
ap += vRel[point] | |
ap = set(ap) | |
return list( x for x in ap if x < bound ) | |
def SmoothWeight(): | |
cmds.progressWindow( title='SmoothWeight', | |
progress=0, | |
status='begin', | |
isInterruptable= False ) | |
selectList = om.MGlobal.getActiveSelectionList() | |
source = selectList.getDagPath(0) | |
smooth = selectList.getDagPath(1) | |
sourceCount = om.MFnMesh(source).numVertices | |
smoothCount = om.MFnMesh(smooth).numVertices | |
sourcePtSet = set(range(sourceCount)) | |
relatetionMap = dict() | |
IE = list() # inner edge points | |
IF = list() # inner face points | |
EE = list() # edge points | |
ieRelMap = list() # n x []*4, 2edge + 4 surd | |
eeRelMap = list() # n x []*2 | |
ifRelMap = list() # n x []*4 | |
# | |
cmds.progressWindow( edit=True, progress=5, status=("Initialization data" ) ) | |
# | |
edgeFacesMap = GetEdgeFacesMap(source) | |
vertexEdgesMap = GetVertexEdgesMap(source) | |
faceVerticesMap = GetFaceVertexMap(source) | |
VertexVerticesMap = GetVertexAroundVertices(source, faceVerticesMap) # [vv, va ] | |
subVertexVerticesMap = GetVertexVertices(smooth) | |
# | |
cmds.progressWindow( edit=True, progress=10, status=("Initialization data" ) ) | |
# | |
# get source weight map | |
skinName, skinNode = getSkinCluster(source) | |
skin = oma.MFnSkinCluster( skinNode ) | |
sourceWeights = GetWeightMap(source, skin, sourceCount) # | |
jointCount = len(skin.influenceObjects()) | |
# bind smooth mesh ---------------------------- | |
# if your smooth mesh already bind joints, comment out | |
cmds.select(d=True) | |
js = cmds.skinCluster(skinName, query= True, inf=source.fullPathName()) | |
cmds.skinCluster(js, smooth.fullPathName(), tsb= True) | |
#-------------------------------------------------- | |
#split edge and inner points , get IFRELSHAPE | |
vIter = om.MItMeshVertex(smooth) | |
for index in xrange(sourceCount, smoothCount): | |
nearVertice = subVertexVerticesMap[index] | |
around = list() | |
for nIndex in nearVertice: | |
if nIndex < sourceCount: | |
around.append(nIndex) | |
if len(around) == 0: | |
IF.append(index) | |
ifRelMap.append( FindAroundPoints(nearVertice, subVertexVerticesMap, sourceCount) ) | |
else: | |
relatetionMap.update( {index: around } ) | |
#split IE and EE | |
for index in relatetionMap.keys(): | |
edge = FindEdgeFromPoints( relatetionMap[index], vertexEdgesMap) | |
connectFaces = edgeFacesMap[edge] | |
if len(connectFaces) == 2: | |
IE.append(index) | |
ieRelMap.append( relatetionMap[index] + list( set( faceVerticesMap[ connectFaces[0] ] ) ^ set( faceVerticesMap[connectFaces[1] ] ) ) ) | |
else: | |
EE.append(index) | |
eeRelMap.append( relatetionMap[index] ) | |
# | |
cmds.progressWindow( edit=True, progress=30, status=("Caculate Source Weight" ) ) | |
# | |
smWeightMap = [ [0.0]*jointCount for i in range(smoothCount) ] | |
for index in xrange(sourceCount): | |
around = VertexVerticesMap[0][index] | |
subAround = VertexVerticesMap[1][index] | |
count = len(around) | |
if count > 2 : | |
smWeightMap[index]= [ i* 0.55 for i in sourceWeights[index] ] | |
subCount = len(subAround) | |
mult = (0.35 / count) if subCount != 0 else (0.45/count) | |
for pt in around: | |
smWeightMap[index] = [ i+j*mult for i, j in zip(smWeightMap[index], sourceWeights[pt]) ] | |
smult = (0.1 / subCount) if subCount != 0 else 0 | |
for pt in subAround: | |
smWeightMap[index] = [ i+j*smult for i, j in zip(smWeightMap[index], sourceWeights[pt]) ] | |
else: | |
smWeightMap[index] = [ i* 0.75 for i in sourceWeights[index] ] | |
for pt in around: | |
smWeightMap[index] = [ i+ j*0.125 for i, j in zip(smWeightMap[index], sourceWeights[pt]) ] | |
# | |
cmds.progressWindow( edit=True, progress=60, status=("Caculate New Weight" ) ) | |
# | |
# get new points weight map | |
for index in xrange(len(IE)): | |
around = ieRelMap[index] | |
pt = IE[index] | |
smWeightMap[pt] = [ (i+j)*0.375 for i, j in zip(sourceWeights[around[0]], sourceWeights[around[1]]) ] | |
count = len(around) | |
mult = 0.25/(count-2) | |
for sub in xrange(2, count): | |
smWeightMap[pt] = [ i+j*mult for i, j in zip(smWeightMap[pt], sourceWeights[ around[sub]]) ] | |
for index in xrange(len(EE)): | |
around = eeRelMap[index] | |
pt = EE[index] | |
smWeightMap[pt] = [ (i+ j)*0.5 for i, j in zip(sourceWeights[around[0]], sourceWeights[around[1]]) ] | |
for index in xrange(len(IF)): | |
around = ifRelMap[index] | |
pt = IF[index] | |
count = len(around) | |
for sub in around: | |
smWeightMap[pt] = [ i+ j/count for i, j in zip( smWeightMap[pt], sourceWeights[sub]) ] | |
# | |
cmds.progressWindow( edit=True, progress=80, status=("Set WeightMap" ) ) | |
# | |
# set weight | |
singleIdComp = om.MFnSingleIndexedComponent() | |
vertexComp = singleIdComp.create( om.MFn.kMeshVertComponent ) | |
singleIdComp.addElements( range(smoothCount) ) | |
influence = convert_List_I_to_MArray( range(jointCount) ) | |
vWeights = convert_List_D_to_MArray( smWeightMap ) | |
sskinName, sskinNode = getSkinCluster(smooth) | |
sskin = oma.MFnSkinCluster( sskinNode ) | |
sskin.setWeights(smooth, vertexComp, influence, vWeights, normalize=True) | |
# | |
cmds.progressWindow( edit=True, progress=100, status=("Finish" ) ) | |
cmds.progressWindow(endProgress=1) | |
# | |
return | |
def convert_List_I_to_MArray(userList): | |
count = len(userList) | |
mArray = om.MIntArray().setLength(count) | |
mArray[:] = userList[:] | |
return mArray | |
def convert_List_D_to_MArray(userList): | |
jCount = len(userList[0]) | |
pCount = len(userList) | |
count = jCount* pCount | |
mArray = om.MDoubleArray().setLength(count) | |
t = []*count | |
for i in xrange(pCount): | |
start = i*jCount | |
t[start : (start+ jCount) ] = userList[i][:] | |
for i in xrange(count): | |
mArray[i] = t[i] | |
return mArray | |
def SmoothWeightApplyFunc(*args): | |
sel = cmds.ls(sl=True) | |
if sel: | |
for ii in sel: | |
skin = mel.eval('findRelatedSkinCluster("{}")'.format(ii)) | |
shape = cmds.listRelatives(ii, c=1, type="mesh")[0] | |
if cmds.objectType(shape) == 'mesh' and skin != '': | |
target = cmds.duplicate(ii,n=ii+'_smoothLv')[0] | |
cmds.polySmooth(target,mth=0,sdt=2,kb=1,ksb=1,khe=1) | |
cmds.DeleteHistory(target) | |
cmds.select(ii,target,r=True) | |
print ii,target | |
SmoothWeight() | |
cmds.select(cl=True) | |
else: | |
cmds.warning('please check your object, it must be mesh or it had been skincluster') | |
def showWindow(*args): | |
global SW_Window | |
SW_Window = "SW_Window" | |
if cmds.window(SW_Window, ex=1): | |
cmds.deleteUI(SW_Window, wnd=1) | |
cmds.window(SW_Window, title="Smooth Weight Apply Func Window", width=400) | |
cmds.columnLayout(adjustableColumn=True) | |
cmds.text(u"\n 选择模型执行,会生成一个新的smooth一次的模型 \n") | |
cmds.button(label=u"Apply", c=SmoothWeightApplyFunc) | |
cmds.showWindow(SW_Window) | |
showWindow() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment