Last active
September 27, 2018 20:30
-
-
Save Onefabis/c78e2f6b7a634bc2ee69d786a6633de6 to your computer and use it in GitHub Desktop.
Create ribbon from selection
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
''' | |
1. Launch the script with the command: | |
import ribb_on | |
ribb_on.makeRibbSurface() | |
This will create NURBS surface which goes through all selected objects that need to be snapped to that surface. | |
After that you will be able to correct the shape of this surface by rotating the profile curve (or maybe scale it). After that you can delete both curves (profile and path) | |
2. Launch the second script: | |
import ribb_on | |
ribb_on.ribbMake( 3, 'parent', 1, 0 ) | |
Where: | |
3 - number of cluster | |
'parent' - type of constraint | |
1 - 'relative' attribute of the cluster | |
0 - attach the surface to another selected objects. | |
''' | |
import maya.OpenMaya as om | |
import maya.mel as mel | |
import itertools | |
import maya.cmds as mc | |
def makeRibbSurface(): | |
global sel | |
sel = mc.ls( sl=1 ) | |
if not mc.objExists( 'grpFollicleRIG' ): | |
mc.group( n='grpFollicleRIG', em=1 ) | |
mc.setAttr( 'grpFollicleRIG.visibility', 0 ) | |
global pts | |
pts = om.MPointArray() | |
curveFn = om.MFnNurbsCurve() | |
for s in sel: | |
pos = mc.xform( s, q=1, ws=1, a=1, rp=1 ) | |
pts.append(*pos) | |
curveObj = curveFn.createWithEditPoints( pts, 3, om.MFnNurbsCurve.kOpen, 0, 0, 1 ) | |
dag = om.MDagPath() | |
path = dag.getAPathTo( curveObj ) | |
mainCurve = path.fullPathName() | |
p = om.MPoint() | |
curveFn2 = om.MFnNurbsCurve() | |
curveFn2.setObject( path ) | |
curveFn2.getPointAtParam( 0, p, om.MSpace.kWorld ) | |
profileCurve = mc.curve( d=1, p=( [-0.5, 0, 0 ], [ 0.5, 0, 0 ]) ) | |
mc.xform( profileCurve, cp=1 ) | |
mc.xform( profileCurve, ws=1, t=( p[0], p[1], p[2] ) ) | |
global surfaceObj | |
surfaceObj = mc.extrude( profileCurve, mainCurve, ch=1, rn=0, po=0, et=2, ucp=1, fpt=1, upn=1, rotation=0, scale=1, rsp=1 ) | |
selSurf = om.MSelectionList() | |
selSurf.add( mc.listRelatives( surfaceObj[0], s=1 )[0] ) | |
dagSurface = om.MDagPath() | |
selSurf.getDagPath( 0, dagSurface ) | |
global apiSurface | |
apiSurface = om.MFnNurbsSurface( dagSurface ) | |
global folArray | |
folArray = [] | |
uutil = om.MScriptUtil() | |
u = uutil.asDoublePtr() | |
vutil = om.MScriptUtil() | |
v = vutil.asDoublePtr() | |
# create surfaceAttach nodes and connect them to the objects | |
for s in xrange(pts.length() ): | |
folicle = mc.createNode( "follicle" ) | |
folicleTr = mc.listRelatives( folicle, type='transform', p=1 ) | |
surfaceShape = mc.listRelatives( surfaceObj, s=1 )[0] | |
mc.connectAttr( folicle + ".outRotate", folicleTr[0] + '.rotate' ) | |
mc.connectAttr( folicle + ".outTranslate", folicleTr[0] + '.translate' ) | |
mc.connectAttr( surfaceShape + '.worldSpace', folicle + '.inputSurface' ) | |
mc.setAttr( folicle + ".simulationMethod", 0 ) | |
apiSurface.getParamAtPoint( pts[s], u, v, 0.1, om.MSpace.kWorld ) | |
sU = mc.getAttr( surfaceShape + '.minMaxRangeU' )[0] | |
sV = mc.getAttr( surfaceShape + '.minMaxRangeV' )[0] | |
mc.setAttr( folicle + '.parameterU', om.MScriptUtil().getDouble(u) / sU[1] ) | |
mc.setAttr( folicle + '.parameterV', om.MScriptUtil().getDouble(v) / sV[1] ) | |
newFol = mc.rename( folicleTr, 'cFollicleAttach' ) | |
newObj = mc.parent( newFol, 'grpFollicleRIG' ) | |
folArray.append( newObj ) | |
def ribbMake( numClusters=3, constraint='parent', rel=1, recreate=0 ): | |
global apiSurface | |
global surfaceObj | |
global pts | |
global sel | |
global folArray | |
newSel = mc.ls( sl=1 ) | |
for s in xrange(pts.length() ): | |
if recreate == 1 and len( newSel ) == len( sel ): | |
print mc.ls( folArray[s] ) | |
exec( 'mc.' + constraint + 'Constraint( mc.ls( folArray[s], l=1 ), newSel[s], mo=1 )' ) | |
else: | |
exec( 'mc.' + constraint + 'Constraint( mc.ls( folArray[s], l=1 ), sel[s], mo=1 )' ) | |
# get all CVs from NURBS surface | |
numUCVs = apiSurface.numCVsInU() | |
numVCVs = apiSurface.numCVsInV() | |
allCVs = [ x for x in itertools.product( range(numUCVs), range( numVCVs ) )] | |
CVName = [] | |
CVCoord = [] | |
CVParam = [] | |
uutil2 = om.MScriptUtil() | |
u2 = uutil2.asDoublePtr() | |
vutil2 = om.MScriptUtil() | |
v2 = vutil2.asDoublePtr() | |
# get max U and V values | |
maxU = mc.getAttr( surfaceObj[0] + '.maxValueU' ) | |
minU = mc.getAttr( surfaceObj[0] + '.minValueU' ) | |
maxV = mc.getAttr( surfaceObj[0] + '.maxValueV' ) | |
minV = mc.getAttr( surfaceObj[0] + '.minValueV' ) | |
lenU = [ maxU if minU == 0 else minU ] | |
lenV = [ maxV if minV == 0 else minV ] | |
for a in allCVs: | |
CVName.append( surfaceObj[0] + '.cv[' + str(a[0]) + '][' + str(a[1]) + ']' ) | |
pos2 = mc.xform( surfaceObj[0] + '.cv[' + str(a[0]) + '][' + str(a[1]) + ']', q=1, ws=1, a=1, t=1 ) | |
pts2 = om.MPointArray() | |
pts2.append( *pos2 ) | |
CVCoord.append( pos2 ) | |
apiSurface.closestPoint( pts2[0], u2, v2, 0, 0.1, om.MSpace.kWorld ) | |
CVParam.append( [om.MScriptUtil().getDouble(u2), om.MScriptUtil().getDouble(v2)] ) | |
clusterUV = [] | |
clusterNames = [] | |
# create clusters | |
for c in xrange(numClusters): | |
cpnt = om.MPoint() | |
inCoord = lenV[0] / ( numClusters - 1 ) * c | |
clusterUV.append( [lenU[0] / 2, inCoord] ) | |
apiSurface.getPointAtParam( lenU[0] / 2, inCoord, cpnt, om.MSpace.kWorld ) | |
newCluster = mc.cluster( CVName ) | |
clusterNames.append( newCluster ) | |
# set Relative mode for the cluster | |
mc.setAttr( newCluster[0] + '.relative', rel ) | |
mc.setAttr( newCluster[0] + 'Handle.rotatePivotX', cpnt[0] ) | |
mc.setAttr( newCluster[0] + 'Handle.rotatePivotY', cpnt[1] ) | |
mc.setAttr( newCluster[0] + 'Handle.rotatePivotZ', cpnt[2] ) | |
mc.setAttr( newCluster[0] + 'Handle.translateX', 0 ) | |
mc.setAttr( newCluster[0] + 'Handle.translateY', 0 ) | |
mc.setAttr( newCluster[0] + 'Handle.translateZ', 0 ) | |
mc.setAttr( newCluster[0] + 'Handle.originX', cpnt[0] ) | |
mc.setAttr( newCluster[0] + 'Handle.originY', cpnt[1] ) | |
mc.setAttr( newCluster[0] + 'Handle.originZ', cpnt[2] ) | |
# Reset it 'bind state' pose to the new one | |
mc.cluster( newCluster[0], e=1, bs=1 ) | |
for c in xrange( len(clusterNames) ): | |
clMDelta = clusterUV[c][-1] - clusterUV[c - 1][-1] | |
clPDelta = clusterUV[c - len(clusterNames) + 1][-1] - clusterUV[c][-1] | |
for x in xrange( len(CVName) ): | |
mc.setAttr('{0}.weightList[0].weights[{1}]'.format(clusterNames[c][0], x), 0 ) | |
if lenV[0] > 0: | |
if clMDelta > 0: | |
for x in xrange( len(CVName) ): | |
if clusterUV[c - 1][-1] <= CVParam[x][-1] <= clusterUV[c][-1]: | |
mc.setAttr('{0}.weightList[0].weights[{1}]'.format(clusterNames[c][0], x), ( CVParam[x][-1] - clusterUV[c - 1][-1] ) / (clusterUV[c][-1] - clusterUV[c - 1][-1]) ) | |
if clPDelta > 0: | |
for x in xrange( len(CVName) ): | |
if clusterUV[c][-1] <= CVParam[x][-1] <= clusterUV[c - len(clusterNames) + 1][-1]: | |
mc.setAttr('{0}.weightList[0].weights[{1}]'.format(clusterNames[c][0], x), 1 - ( CVParam[x][-1] - clusterUV[c][-1] ) / (clusterUV[c - len(clusterNames) + 1][-1] - clusterUV[c][-1]) ) | |
else: | |
if clMDelta < 0: | |
for x in xrange( len(CVName) ): | |
if clusterUV[c - 1][-1] >= CVParam[x][-1] >= clusterUV[c][-1]: | |
mc.setAttr('{0}.weightList[0].weights[{1}]'.format(clusterNames[c][0], x), ( CVParam[x][-1] - clusterUV[c - 1][-1] ) / (clusterUV[c][-1] - clusterUV[c - 1][-1]) ) | |
if clPDelta < 0: | |
for x in xrange( len(CVName) ): | |
if clusterUV[c][-1] >= CVParam[x][-1] >= clusterUV[c - len(clusterNames) + 1][-1]: | |
mc.setAttr('{0}.weightList[0].weights[{1}]'.format(clusterNames[c][0], x), 1 - ( CVParam[x][-1] - clusterUV[c][-1] ) / (clusterUV[c - len(clusterNames) + 1][-1] - clusterUV[c][-1]) ) | |
#makeRibbSurface() | |
#ribbMake( 5, 'parent', 1, 0 ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey cool script!
Wanted to share mine for a twisty limb.
really annoying how 'cMuscleSurfAttachSetup();' has like no documentation or python equivalent!