def strokePath(node, radius=.1): """ Create a nurbs surface from a curve control """ curveNodes = separateShapes(node) for curveNode in curveNodes: shape = curveNode.listRelatives(type='nurbsCurve')[0] t = pm.pointOnCurve(shape, p=0, nt=1) pos = pm.pointOnCurve(shape, p=0) cir = pm.circle(r=radius)[0] pm.xform(cir, t=pos, ws=1) #align the circule along the curve l = pm.spaceLocator() pm.xform(l, t=[pos[0]+t[0], pos[1]+t[1], pos[2]+t[2]], ws=1) pm.delete(pm.aimConstraint(l, cir, aimVector=[0,0,1])) pm.delete(l) newxf = pm.extrude(cir, curveNode, rn=False, po=0, et=2, ucp=1, fpt=1, upn=1, scale=1, rsp=1, ch=1)[0] pm.delete(cir) pm.delete(curveNode.listRelatives(type='nurbsCurve')) parentShape(curveNode, newxf) if len(curveNodes) > 1: for i in range(1, len(curveNodes)): parentShape(curveNodes[0], curveNodes[i]) return curveNodes[0]
def wiggleJointChain(strPnt, endPnt, side='FL', chainPos='Upper'): ''' create joint chain between two points (strPnt & endPnt). require name string of strPnt & endPnt ''' strPos = pm.xform( strPnt, q=True, ws=True, translation=True ) endPos = pm.xform( endPnt, q=True, ws=True, translation=True ) if side.endswith('L'): sideLabel = 1 elif side.endswith('R'): sideLabel = 2 ikSpCrv = pm.curve( degree=2, editPoint=( strPos, endPos) ) ikSpCrv.rename( 'wiggle_%s_%s_CRV'%(side, chainPos) ) ikSpCrvShp = ikSpCrv.listRelatives(shapes=True)[0] pm.select(clear=True) jnt2pos = pm.pointOnCurve( ikSpCrv, pr=0.3333, turnOnPercentage=True) jnt3pos = pm.pointOnCurve( ikSpCrv, pr=0.6667, turnOnPercentage=True ) jntPos = ( strPos, jnt2pos, jnt3pos, endPos ) jntList = [] for pnt in jntPos: jName = 'Wiggle_%s_%s_%02d'%(side, chainPos, jntPos.index(pnt)+1) newJoint = pm.joint(name=jName, p=pnt) newJoint.side.set(sideLabel) newJoint.__getattr__('type').set(18) newJoint.otherType.set(jName) jntList.append(newJoint) pm.joint( jntList[0], edit=True, orientJoint='xyz', secondaryAxisOrient='xup', children=True, zeroScaleOrient=True ) ikHandle = pm.ikHandle( name='Wiggle_%s_%s_ikHandle'%(side, chainPos), solver='ikSplineSolver', createCurve=False, curve=ikSpCrvShp, startJoint=jntList[0].name(), endEffector=jntList[-1].name(), rootOnCurve=False, createRootAxis=True, parentCurve=False ) jntGrp = jntList[0].listRelatives(parent=True)[0] jntGrp.rename('Wiggle_%s_%s'%(side, chainPos)) crvInfo = pm.createNode('curveInfo', name='crvInf_wiggle_%s_%s'%(side, chainPos)) multDiv1 = pm.createNode('multiplyDivide', name='md_wiggle_%s_%s_01'%(side, chainPos)) multDiv2 = pm.createNode('multiplyDivide', name='md_wiggle_%s_%s_02'%(side, chainPos)) ikSpCrvShp.worldSpace >> crvInfo.inputCurve arcLgt = crvInfo.arcLength.get() multDiv1.input2X.set(arcLgt) multDiv1.operation.set(2) spacing = jntList[1].tx.get() multDiv2.input2X.set(spacing) multDiv1.outputX >> multDiv2.input1X crvInfo.arcLength >> multDiv1.input1X for jnt in jntList[1:]: multDiv2.outputX >> jnt.tx return ikSpCrvShp, ikSpCrv, ikHandle[0], jntGrp
def createHighlight(mesh, lightType=mayaLights["Spot"], offset=6): """ Create Light based on curve drawn on object """ # Get the currently selected curve curveA = getSelection() # Get the start and end points of the curve as Vectors crv_posA = dt.Vector(pm.pointOnCurve(curveA, pr=0)) crv_posB = dt.Vector(pm.pointOnCurve(curveA, pr=curveA.maxValue.get())) # Calculate the mid point midPoint = (crv_posA + crv_posB) / 2 # Get closest point & normal on mesh pointOnMesh_set = mesh.getClosestPointAndNormal(midPoint, space="world") pointOnMesh = pointOnMesh_set[0] pointOnMesh_normal = pointOnMesh_set[1] pm.spaceLocator(p=pointOnMesh) # For debug/vis # Create dummy camera cam = pm.camera() camera = cam[0] camera.setTranslation(pointOnMesh + pointOnMesh_normal * offset) pm.viewLookAt(camera, pos=pointOnMesh) # Create light createLight(lightType, camera.getTranslation(), camera.getRotation()) # Delete dummy camera pm.delete(camera)
def getPlaneDirection(crv): curvePosition = pm.pointOnCurve(crv, pr=0, p=True) curveTangent = pm.pointOnCurve(crv, pr=0, tangent=True) curvePosVec = MVector(curvePosition[0],curvePosition[1],curvePosition[2]) curveTangentVec = MVector(curveTangent[0],curveTangent[1],curveTangent[2]).normal() yVec = MVector(0,1,0) dirVec = yVec ^ curveTangentVec return dirVec
def IK_createAveObj(cur, number, s="group"): newCur = pm.duplicate(cur, rr=1, n=cur + "_copyCurve1") curInfo = pm.arclen(cur, ch=1) ns = int(curInfo.arcLength.get()) pm.delete(curInfo) pm.rebuildCurve(newCur, ch=1, rpo=1, rt=0, end=1, kr=0, kcp=0, kep=1, kt=0, s=ns * 100, d=3, tol=0.01) allNewInfo = [] aimObj = [] p = 1.0 / float((number - 1)) prF = 0.0 if s == "position": allPoistion = [] for i in range(number): if i == number - 1: NewInfo = pm.pointOnCurve(newCur, ch=1, top=1, pr=1) else: NewInfo = pm.pointOnCurve(newCur, ch=1, top=1, pr=prF) prF += p allNewInfo.append(NewInfo) t = pm.getAttr(NewInfo + ".position") if s == "position": allPoistion.append(t) if s == "group": obj = pm.group(em=1, n=cur + "_AimGrp" + str(i + 1)) aimObj.append(obj) pm.setAttr(obj + ".translate", t) cmds.select(cl=1) pm.delete(allNewInfo, newCur) if s == "position": return allPoistion if s == "group": return aimObj
def IK_objPosition(cur, obj): vec = [] crv = str(pm.ls(cur)[0].listRelatives(s=1)[0]) u = [ IK_getUParam(cmds.xform(str(obj[i - 1]), q=1, ws=1, t=1), crv) for i in range(1, len(obj) + 1) ] l = u[-1] cv = [ u[0], ] for i in range(1, len(u) - 1): cv.append(((u[i] - u[i - 1]) * 0.5) + u[i - 1]) cv.append(((u[i] - u[i - 1]) * 0.9) + u[i - 1]) cv.append(u[i]) cv.append(((u[i + 1] - u[i]) * 0.1) + u[i]) if len(u) > 1: cv.append(((u[-1] - u[-2]) * 0.5) + u[-2]) cv.append(l) ii = 1 for p in cv: po = pm.pointOnCurve(cur, ch=1, pr=p) info = pm.rename(po, cur + "_curveInfo" + str(i)) vec.append(info.getAttr("position")) pm.delete(info) ii += 1 pm.delete(obj) return vec
def CurveLoft(crv, geom, size, norDir, nm): try: crvSh = crv.listRelatives(s=1, type='nurbsCurve')[0] except: pm.warning('%s is not nurbsCurve') return tmpOC = pm.createNode('nearestPointOnCurve', n='TmpOC') crv.ws >> tmpOC.inputCurve copyCrvA = crv.duplicate(n='%sCopyACrv' % crv.name().replace('Crv', ''))[0] copyCrvB = crv.duplicate(n='%sCopyBCrv' % crv.name().replace('Crv', ''))[0] cvSz = int(crv.spans.get()) if crv.d.get() == 3: cvSz = cvSz + 3 upvec = dt.Vector(int(norDir[0]), int(norDir[1]), int(norDir[2])) for i in xrange(cvSz): tmpOC.inPosition.set(crv.cv[i].getPosition(space='world')) tVec = pm.pointOnCurve(crv, pr=tmpOC.parameter.get(), nt=1) cVecA = dt.cross(upvec, dt.Vector(tVec)) cVecB = dt.cross(dt.Vector(tVec), upvec) pm.move(copyCrvA.cv[i], cVecA * size, r=1) pm.move(copyCrvB.cv[i], cVecB * size, r=1) geo = pm.loft(copyCrvB, copyCrvA, ch=1, u=1, c=0, ar=1, d=3, ss=1, rn=0, po=int(geom), rsn=1) mel.eval('DeleteHistory %s' % geo[0].name()) pm.delete(tmpOC, copyCrvA, copyCrvB) return geo[0]
def build(self): """ Build system""" self.all_jnts = [] self.all_pointOnCurve_nodes = [] self.Pos = [] # Creation of all joints self.all_jnts = [pm.joint(rad=self._radius) for x in range(self._interval)] for joint in self.all_jnts: pm.parent(joint, w=True) adb.makeroot_func(joint) # Creation of Point to Curve Nodes self.all_pointOnCurve_nodes = [pm.pointOnCurve(self._curve, ch=True, top=True) for x in range(self._interval)] for node, joint in zip(self.all_pointOnCurve_nodes, self.all_jnts): pm.PyNode(node).positionX >> (pm.PyNode(joint).getParent()).translateX pm.PyNode(node).positionY >> (pm.PyNode(joint).getParent()).translateY pm.PyNode(node).positionZ >> (pm.PyNode(joint).getParent()).translateZ # Find all position Nintervalls = self._interval - 1 for i in range(0, Nintervalls): factor = 1 / float((Nintervalls)) oPos = factor * i self.Pos.append(oPos) self.Pos.append(1) for oPosition, oNode in zip(self.Pos, self.all_pointOnCurve_nodes): pm.PyNode(oNode).parameter.set(oPosition) pm.select(None)
def curve_getPoint(curve, place, cv=False): '''Returns points on a curve Args: curve (pm.PyNode): curve to be queried place (float): tells what percent and or cv to choose from, if cv, use int cv (boolean): tells whether to use cv positions or not Returns: (vector): position of point on curve or None if CV doesn't exist Usage: curve_getPoint(pm.ls(sl=True)[0], .8) - Query Percentage curve_getPoint(pm.ls(sl=True)[0], 5, cv=True)) - Query CV ''' pos=[0,0,0] if cv: if place in range(len(curve.getShape().getCVs())): pos = curve.getShape().getCV(place) else: return None else: poc = pm.pointOnCurve(curve, ch=True, top=True) poc = pm.PyNode(poc) poc.parameter.set(place) pos = poc.position.get() pm.delete(poc) return pos
def point_on_curve_position(curve, parameter): u"""获取曲线上cv点的位置信息 :param curve: 曲线的名字 :param parameter: 曲线上的参数值 :return: Returns the (x,y,z) position of curve at parameter. """ return pm.pointOnCurve(curve, pr=parameter, p=True)
def get_closest_crv_pair_list(self, driver_tfm, driven_tfm): driver_crv_list = list(set(pm.listRelatives(pm.listRelatives(driver_tfm, ad = True, type = 'nurbsCurve'), parent = True))) driven_crv_list = list(set(pm.listRelatives(pm.listRelatives(driven_tfm, ad = True, type = 'nurbsCurve'), parent = True))) driver_pos_info = [] for driver in driver_crv_list: pos = pm.pointOnCurve(driver, pr = 0) driver_pos_info.append([pos, driver]) print driver_pos_info pair_list = [] for driven in driven_crv_list: pos = pm.pointOnCurve(driven, pr = 0) proximity_list = [] for driver_pos in driver_pos_info: distance = self.get_distance(pos, driver_pos[0]) proximity_list.append([distance, driver_pos[1]]) proximity_list.sort() pair_list.append([proximity_list[0][1], driven]) return pair_list
def distributeCrv( transformNodes, curve=None, uniform=True ): nodes = [pm.PyNode(node) for node in transformNodes] crv = pm.PyNode(curve) crvShape = crv.getShape() nodeNums = len(nodes) contMembers = [] if uniform: rebCrv, reb = 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 ) crvShape = rebCrv.getShapes( type='nurbsCurve' )[0] rebCrv.rename( crv+'_rebCrv' ) reb.rename( crv+'_rebuildCrv' ) contMembers.append( pm.parentConstraint( crv, rebCrv ) ) contMembers.append( pm.scaleConstraint( crv, rebCrv ) ) contMembers.append( rebCrv ) contMembers.append( reb ) unit = None if crv.form() == 'periodic': unit = (1.0/nodeNums) else: unit = (1.0/(nodeNums-1)) for i, node in enumerate( nodes ): pointOnCurve = pm.PyNode( pm.pointOnCurve( crvShape, ch=True ) ) pointOnCurve.rename( node+'_POC' ) pointOnCurve.turnOnPercentage.set(True) pointOnCurve.parameter.set( unit*i ) pointOnCurve.p >> node.t pointOnCurve.setAttr('parameter', keyable=True) contMembers.append( pointOnCurve ) cont = pm.container( type='dagContainer', addNode=contMembers, n=crv+'_distributeCrv#' ) cont.v.set(False) return cont
def get_points_on_curve(inputcurve, amount=3): infoNode = pm.PyNode(pm.pointOnCurve(inputcurve, ch=True, top=True)) try: inc = 1.0 / (amount - 1) for i in range(amount): infoNode.parameter.set(i * inc) pos = infoNode.position.get() norm = infoNode.normal.get() tang = infoNode.tangent.get() crossV = norm.cross(tang) pmatrix = pm.dt.Matrix(norm.x, norm.y, norm.z, 0, tang.x, tang.y, tang.z, 0, crossV.x, crossV.y, crossV.z, 0, pos.x, pos.y, pos.z, 0) yield (pmatrix.translate, pmatrix.rotate) except ZeroDivisionError: log.error('Amount is too low, current:{}, minimum:{}'.format( amount, 2)) raise finally: pm.delete(infoNode)
def LsyIK_stretch(cur, obj, scaleObj): crv = str(pm.ls(cur)[0].listRelatives(s=1)[0]) u = [ IK_getUParam(cmds.xform(str(obj[i - 1]), q=1, ws=1, t=1), crv) for i in range(1, len(obj) + 1) ] info = [] for i in range(len(u)): po = pm.pointOnCurve(cur, ch=1, pr=u[i]) info.append(pm.rename(po, cur + "_curveInfo" + str(i))) t = [i for i in range(0, len(info) - 1, 2)] for i in range(0, len(info) - 1): dis = pm.createNode("distanceBetween", n=obj[i + 1] + "_disBet") pm.connectAttr(info[i] + ".position", dis + ".point1") pm.connectAttr(info[i + 1] + ".position", dis + ".point2") if i in t: mul = [ pm.createNode("multiplyDivide", n=obj[i + 1] + "_mul" + x) for x in ["1", "2"] ] [pm.setAttr(s + ".operation", 2) for s in mul] pm.connectAttr(dis + ".distance", mul[0] + ".input1X") pm.connectAttr(scaleObj + ".sy", mul[0] + ".input2X") pm.connectAttr(mul[0] + ".outputX", mul[1] + ".input1X") pm.setAttr(mul[1] + ".input2X", pm.getAttr(mul[1] + ".input1X")) pm.connectAttr(mul[1] + ".outputX", obj[i] + ".sx") else: pm.connectAttr(dis + ".distance", mul[0] + ".input1Z") pm.connectAttr(scaleObj + ".sy", mul[0] + ".input2Z") pm.connectAttr(mul[0] + ".outputZ", mul[1] + ".input1Z") pm.setAttr(mul[1] + ".input2Z", pm.getAttr(mul[1] + ".input1Z")) pm.connectAttr(mul[1] + ".outputZ", obj[i] + ".sx")
def create_shapes(*args): print('This will create shapes') num = slider1.getValue() print('Number of shapes to be created:', num) i = 0 while i < num: value = float(i) / num angle = random.randint(0, 359) radius = random.uniform(0.5, 2) height = random.uniform(0.5, 1) x, y, z = pm.pointOnCurve('curve1', pr=value, turnOnPercentage=True) x1 = random.uniform(x - 3, x + 3) y1 = random.uniform(y - 3, y + 3) z1 = random.uniform(z - 3, z + 3) shape = options.getValueArray4() j = random.randint(0, 3) if shape[j] == True: if j == 0: figure = pm.polyTorus(r=radius, sr=0.25) pm.move(x1, y1, z1, figure) i += 1 elif j == 1: figure = pm.polyCone(sx=1, sy=1.5, sz=0.5, r=radius, h=height) pm.move(x1, y1, z1, figure) i += 1 elif j == 2: figure = pm.polySphere(r=radius) pm.move(x1, y1, z1, figure) i += 1 elif j == 3: figure = pm.polyCylinder(r=radius, h=height) pm.move(x1, y1, z1, figure) i += 1 pm.select(figure) pm.rotate(angle, 0, 0, r=True) pm.select(clear=True)
def positionRig(self): # # 로케이터 생성 # LOC = None if self.locatorShape=='locator': LOC = pm.spaceLocator( n='locOnCrv#') else: LOC = pm.group( n='grpOnCrv#', em=True) if self.name: LOC.rename( self.name ) LOC.addAttr( 'parameter', sn='pr', dv=self.param, keyable=True ) LOC.addAttr( 'turnOnPercentage', sn='top', dv=self.turnOnPercentage, at='bool', keyable=True ) LOC.it.set(False) # # pointOnCurve 리깅 # pntOnCrv = pm.PyNode( pm.pointOnCurve( self.curve, parameter=self.param, ch=True ) ) pntOnCrv.turnOnPercentage.set(True) pntOnCrv.setAttr('parameter', keyable=True) pntOnCrv.setAttr('turnOnPercentage', keyable=True) pntOnCrv.rename( LOC+'_POC' ) # # Position 리깅 # LOC.parameter >> pntOnCrv.parameter LOC.turnOnPercentage >> pntOnCrv.turnOnPercentage pntOnCrv.position >> LOC.t self.locator = LOC self.pointOnCurve = pntOnCrv
def get_pos(crv, param=0): # dt.Vector return dt.Vector(pm.pointOnCurve(crv, pr=param, p=True))
def build_joint_chain(name=None, crv=None, order=None, num=None, loc=None, reg_node=None, log=False): '''Given a valid curve, build joint chain along curve, num joints long Attributes: name -- Prefix name for plane. Str crv -- Curve to use as build guide. pm.nt.Transform order -- ['xyz','xzy','yxz','yzx','zxy','zyx'] num -- Number of joints. 3 - 50, Int loc -- Used to set aim of secondary axis nt.Transform reg_node -- Registratioin node. nt.Transform log -- Output logging messages. Bool ''' general.check_type(name, 'name', [str]) general.check_type(crv, 'crv', [pm.nt.Transform]) general.check_type(order, 'order', [str]) general.check_type(num, 'num', [int]) general.check_type(loc, 'loc', [pm.nt.Transform]) orders = ['xyz', 'xzy', 'yxz', 'yzx', 'zxy', 'zyx'] if order not in orders: raise errors.InputError('order', order, orders) if num < 3 or num > 50: raise errors.InputError('num', num, 'Range: 3 - 50') loc = loc.duplicate()[0] chain = [] loc_v = None incr = float(1.0 / num) if log: str_1 = 'Curve Length: ', pm.arclen(crv) str_2 = 'Increment: ', incr general.logging.debug(str_1) general.logging.debug(str_2) param = 0 pm.select(clear=1) for i in range(num): pos = pm.pointOnCurve(crv, pr=param, p=True, top=True) if i == 0: # Get vector to locator pos_v = pm.dt.Vector(pos) loc_pos = pm.dt.Vector(pm.xform(loc, q=1, ws=1, rp=1)) loc_v = loc_pos - pos_v if log: str_1 = 'Jnt Pos: ', pos_v str_2 = 'Loc Pos: ', loc_pos str_3 = 'Loc Vec: ', loc_v general.logging.debug(str_1) general.logging.debug(str_2) general.logging.debug(str_3) j = pm.joint(p=pos, name='%s_Jnt_%s' % (name, (i + 1))) chain.append(j) if log: str_1 = 'Created Joint: ', j str_2 = 'Parameter: ', param str_3 = 'Pos: ', pos str_4 = 'Curve: ', crv general.logging.debug(str_1) general.logging.debug(str_2) general.logging.debug(str_3) general.logging.debug(str_4) param += incr if log: str_1 = 'Chain: ', str(chain) general.logging.debug(str_1) # aim vector aim_v = [] if order[0].lower() == 'x': aim_v = [1, 0, 0] if order[0].lower() == 'y': aim_v = [0, 1, 0] if order[0].lower() == 'z': aim_v = [0, 0, 1] # up vector up_v = [] if order[1].lower() == 'x': up_v = [1, 0, 0] if order[1].lower() == 'y': up_v = [0, 1, 0] if order[1].lower() == 'z': up_v = [0, 0, 1] for jnt in chain[:-1]: # Snap/parent locator to jnt pm.parent(loc, jnt) loc.setTranslation(0) loc.setRotation([0, 0, 0]) # move by loc_v pm.move(loc_v[0], loc_v[1], loc_v[2], loc, r=1) pm.parent(loc, w=1) # Remove joint from hierarchy p = jnt.getParent() c = jnt.getChildren() try: pm.parent(jnt, w=1) except: pass pm.parent(c, w=1) # Aim to child pm.delete( pm.aimConstraint(c, jnt, aim=aim_v, wu=up_v, wut='object', wuo=loc, mo=0)) # Reinsert to heirarchy if c: pm.parent(c, jnt) if p: pm.parent(jnt, p) # Oreint last joint to none pm.joint(chain[-1], e=1, oj='none', zso=True) if not reg_node: reg_node = control.create_register_node(name) control.register_object(reg_node, '%s_chain_root' % name, chain[0]) pm.select(clear=1) pm.delete(loc) return reg_node, chain
def build_joint_chain(name=None, crv=None, order=None, num=None, loc=None, reg_node=None, log=False): '''Given a valid curve, build joint chain along curve, num joints long Attributes: name -- Prefix name for plane. Str crv -- Curve to use as build guide. pm.nt.Transform order -- ['xyz','xzy','yxz','yzx','zxy','zyx'] num -- Number of joints. 3 - 50, Int loc -- Used to set aim of secondary axis nt.Transform reg_node -- Registratioin node. nt.Transform log -- Output logging messages. Bool ''' general.check_type(name, 'name', [str]) general.check_type(crv, 'crv', [pm.nt.Transform]) general.check_type(order, 'order', [str]) general.check_type(num, 'num', [int]) general.check_type(loc, 'loc', [pm.nt.Transform]) orders = ['xyz', 'xzy', 'yxz', 'yzx', 'zxy', 'zyx'] if order not in orders: raise errors.InputError('order', order, orders) if num < 3 or num > 50: raise errors.InputError('num', num, 'Range: 3 - 50') loc = loc.duplicate()[0] chain = [] loc_v = None incr = float(1.0/num) if log: str_1 = 'Curve Length: ', pm.arclen(crv) str_2 = 'Increment: ', incr general.logging.debug(str_1) general.logging.debug(str_2) param = 0 pm.select(clear=1) for i in range(num): pos = pm.pointOnCurve(crv, pr=param, p=True, top=True) if i == 0: # Get vector to locator pos_v = pm.dt.Vector(pos) loc_pos = pm.dt.Vector(pm.xform(loc, q=1, ws=1, rp=1)) loc_v = loc_pos - pos_v if log: str_1 = 'Jnt Pos: ', pos_v str_2 = 'Loc Pos: ', loc_pos str_3 = 'Loc Vec: ', loc_v general.logging.debug(str_1) general.logging.debug(str_2) general.logging.debug(str_3) j = pm.joint(p=pos, name='%s_Jnt_%s' % (name, (i+1))) chain.append(j) if log: str_1 = 'Created Joint: ', j str_2 = 'Parameter: ', param str_3 = 'Pos: ', pos str_4 = 'Curve: ', crv general.logging.debug(str_1) general.logging.debug(str_2) general.logging.debug(str_3) general.logging.debug(str_4) param += incr if log: str_1 = 'Chain: ', str(chain) general.logging.debug(str_1) # aim vector aim_v = [] if order[0].lower() == 'x': aim_v = [1, 0, 0] if order[0].lower() == 'y': aim_v = [0, 1, 0] if order[0].lower() == 'z': aim_v = [0, 0, 1] # up vector up_v = [] if order[1].lower() == 'x': up_v = [1, 0, 0] if order[1].lower() == 'y': up_v = [0, 1, 0] if order[1].lower() == 'z': up_v = [0, 0, 1] for jnt in chain[:-1]: # Snap/parent locator to jnt pm.parent(loc, jnt) loc.setTranslation(0) loc.setRotation([0, 0, 0]) # move by loc_v pm.move(loc_v[0], loc_v[1], loc_v[2], loc, r=1) pm.parent(loc, w=1) # Remove joint from hierarchy p = jnt.getParent() c = jnt.getChildren() try: pm.parent(jnt, w=1) except: pass pm.parent(c, w=1) # Aim to child pm.delete(pm.aimConstraint(c, jnt, aim=aim_v, wu=up_v, wut='object', wuo=loc, mo=0)) # Reinsert to heirarchy if c: pm.parent(c, jnt) if p: pm.parent(jnt, p) # Oreint last joint to none pm.joint(chain[-1], e=1, oj='none', zso=True) if not reg_node: reg_node = control.create_register_node(name) control.register_object(reg_node, '%s_chain_root' % name, chain[0]) pm.select(clear=1) pm.delete(loc) return reg_node, chain
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 create(self): self.nodes = [] #------------------------------ # # Create Ctrler # #------------------------------ self.root_grp = pm.group( n='TwistHelper_grp', em=True) self.constMe_to_parent = pm.group( n='constMe_to_parent', em=True) self.constMe_to_start = pm.group( n='constMe_to_start', em=True) self.constMe_to_mid = pm.group( n='constMe_to_mid', em=True ) self.constMe_to_end = pm.group( n='constMe_to_end', em=True) self.doNotTouch_grp = pm.group( n='doNotTouch_grp', em=True) pm.parent( self.constMe_to_start, self.constMe_to_mid, self.constMe_to_end, self.constMe_to_parent) pm.parent( self.constMe_to_parent, self.doNotTouch_grp, self.root_grp ) self.start_T_anim = pm.group( n='start_T_anim', em=True) self.end_T_anim = pm.group( n='end_T_anim', em=True) pm.parent( self.start_T_anim, self.constMe_to_start ) pm.parent( self.end_T_anim, self.constMe_to_end ) self.mid_T_anim = pm.group( n='mid_T_anim', em=True ) self.mid1_T_anim = pm.group( n='mid1_T_anim', em=True ) self.mid2_T_anim = pm.group( n='mid2_T_anim', em=True ) pm.parent( self.mid1_T_anim, self.mid2_T_anim, self.mid_T_anim ) pm.parent( self.mid_T_anim, self.constMe_to_mid ) self.start_R_result = pm.group( n='start_R_result', em=True) self.start_up_anim = pm.group( n='start_up_anim', em=True) pm.parent( self.start_R_result, self.start_up_anim, self.start_T_anim ) self.end_R_result = pm.group( n='end_R_result', em=True) self.end_up_anim = pm.group( n='end_up_anim', em=True) pm.parent( self.end_R_result, self.end_up_anim, self.end_T_anim ) self.doNotTouch_grp.v.set(False) # 어트리뷰트 잠금 self._lockAndHideAttr([self.start_up_anim, self.end_up_anim],['rx','ry','rz','sx','sy','sz']) self._lockAndHideAttr([self.constMe_to_start, self.constMe_to_mid, self.constMe_to_end, self.mid_T_anim, self.constMe_to_parent],['sx','sy','sz','v']) self._lockAndHideAttr([self.start_R_result, self.end_R_result],['sx','sy','sz','v']) self._lockAndHideAttr([self.start_T_anim, self.end_T_anim, self.mid1_T_anim, self.mid2_T_anim],['rx','ry','rz','sx','sy','sz','v']) self._lockAndHideAttr([self.doNotTouch_grp, self.root_grp],['tx','ty','tz','rx','ry','rz','sx','sy','sz']) self.nodes.extend([self.root_grp, self.constMe_to_parent, self.constMe_to_start, self.constMe_to_mid, self.constMe_to_end, self.doNotTouch_grp, self.start_T_anim, self.end_T_anim, self.mid_T_anim, self.mid1_T_anim, self.mid2_T_anim, self.start_R_result, self.start_up_anim]) self.nodes.extend([self.end_R_result, self.end_up_anim]) #------------------------------ # # config Attribute # #------------------------------ ctrl = self.root_grp ctrl.addAttr('aimAxis', at='enum', en='PositiveX:NegativeX:', keyable=False) # IK핸들의 Advanced Twist Controls 세팅이 -x축은 고려되어 있지 않음. 의미 없음. ctrl.addAttr('aimVector', at='double3') ctrl.addAttr('aimVectorX', at='double', p='aimVector', keyable=False) ctrl.addAttr('aimVectorY', at='double', p='aimVector', keyable=False) ctrl.addAttr('aimVectorZ', at='double', p='aimVector', keyable=False) ctrl.addAttr('upAxis', at='enum', en='PositiveY:NegativeY:ClosetY:PositiveZ:NegativeZ:ClosetZ:', keyable=True) ctrl.addAttr('upVector', at='double3') ctrl.addAttr('upVectorX', at='double', p='upVector', keyable=True) ctrl.addAttr('upVectorY', at='double', p='upVector', keyable=True) ctrl.addAttr('upVectorZ', at='double', p='upVector', keyable=True) ctrl.addAttr('startWorldUpVector', at='double3') ctrl.addAttr('startWorldUpVectorX', at='double', p='startWorldUpVector', keyable=True) ctrl.addAttr('startWorldUpVectorY', at='double', p='startWorldUpVector', keyable=True) ctrl.addAttr('startWorldUpVectorZ', at='double', p='startWorldUpVector', keyable=True) ctrl.addAttr('endWorldUpVector', at='double3') ctrl.addAttr('endworldUpVectorX', at='double', p='endWorldUpVector', keyable=True) ctrl.addAttr('endworldUpVectorY', at='double', p='endWorldUpVector', keyable=True) ctrl.addAttr('endworldUpVectorZ', at='double', p='endWorldUpVector', keyable=True) ctrl.aimVector.set(self.aimVector) ctrl.upVector.set(self.upVector) ctrl.startWorldUpVector.set(self.startWorldUpVector) ctrl.endWorldUpVector.set(self.endWorldUpVector) pm.setDrivenKeyframe( ctrl.aimVectorX, value= 1, currentDriver=ctrl.aimAxis, driverValue=0 ) # positiveX pm.setDrivenKeyframe( ctrl.aimVectorY, value= 0, currentDriver=ctrl.aimAxis, driverValue=0 ) # positiveX pm.setDrivenKeyframe( ctrl.aimVectorZ, value= 0, currentDriver=ctrl.aimAxis, driverValue=0 ) # positiveX pm.setDrivenKeyframe( ctrl.aimVectorX, value=-1, currentDriver=ctrl.aimAxis, driverValue=1 ) # negativeX pm.setDrivenKeyframe( ctrl.aimVectorY, value= 0, currentDriver=ctrl.aimAxis, driverValue=1 ) # negativeX pm.setDrivenKeyframe( ctrl.aimVectorZ, value= 0, currentDriver=ctrl.aimAxis, driverValue=1 ) # negativeX pm.setDrivenKeyframe( ctrl.upVectorX, value= 0, currentDriver=ctrl.upAxis, driverValue=0 ) # positiveY pm.setDrivenKeyframe( ctrl.upVectorY, value= 1, currentDriver=ctrl.upAxis, driverValue=0 ) # positiveY pm.setDrivenKeyframe( ctrl.upVectorZ, value= 0, currentDriver=ctrl.upAxis, driverValue=0 ) # positiveY pm.setDrivenKeyframe( ctrl.upVectorX, value= 0, currentDriver=ctrl.upAxis, driverValue=1 ) # negativeY pm.setDrivenKeyframe( ctrl.upVectorY, value=-1, currentDriver=ctrl.upAxis, driverValue=1 ) # negativeY pm.setDrivenKeyframe( ctrl.upVectorZ, value= 0, currentDriver=ctrl.upAxis, driverValue=1 ) # negativeY pm.setDrivenKeyframe( ctrl.upVectorX, value= 0, currentDriver=ctrl.upAxis, driverValue=3 ) # positiveZ pm.setDrivenKeyframe( ctrl.upVectorX, value= 0, currentDriver=ctrl.upAxis, driverValue=2 ) # negativeY pm.setDrivenKeyframe( ctrl.upVectorY, value= 1, currentDriver=ctrl.upAxis, driverValue=2 ) # negativeY pm.setDrivenKeyframe( ctrl.upVectorZ, value= 0, currentDriver=ctrl.upAxis, driverValue=2 ) # negativeY pm.setDrivenKeyframe( ctrl.upVectorX, value= 0, currentDriver=ctrl.upAxis, driverValue=3 ) # positiveZ pm.setDrivenKeyframe( ctrl.upVectorY, value= 0, currentDriver=ctrl.upAxis, driverValue=3 ) # positiveZ pm.setDrivenKeyframe( ctrl.upVectorZ, value= 1, currentDriver=ctrl.upAxis, driverValue=3 ) # positiveZ pm.setDrivenKeyframe( ctrl.upVectorX, value= 0, currentDriver=ctrl.upAxis, driverValue=4 ) # negativeZ pm.setDrivenKeyframe( ctrl.upVectorY, value= 0, currentDriver=ctrl.upAxis, driverValue=4 ) # negativeZ pm.setDrivenKeyframe( ctrl.upVectorZ, value=-1, currentDriver=ctrl.upAxis, driverValue=4 ) # negativeZ pm.setDrivenKeyframe( ctrl.upVectorX, value= 0, currentDriver=ctrl.upAxis, driverValue=5 ) # negativeZ pm.setDrivenKeyframe( ctrl.upVectorY, value= 0, currentDriver=ctrl.upAxis, driverValue=5 ) # negativeZ pm.setDrivenKeyframe( ctrl.upVectorZ, value= 1, currentDriver=ctrl.upAxis, driverValue=5 ) # negativeZ ctrl.setAttr('upVectorX', keyable=False ) ctrl.setAttr('upVectorY', keyable=False ) ctrl.setAttr('upVectorZ', keyable=False ) # # # base Curve # # crv = pm.curve( n='base_crv', d=3, p=[(0,0,0),(0,0,0),(0,0,0),(0,0,0)], k=[0,0,0,1,1,1] ) pm.parent( crv, self.doNotTouch_grp ) crv.it.set(False) self.nodes.append(crv) # create curve cv clusters start_crv_clst = pm.cluster( crv.cv[0], wn=(self.start_T_anim,self.start_T_anim) )[0] mid1_crv_clst = pm.cluster( crv.cv[1], wn=(self.mid1_T_anim, self.mid1_T_anim) )[0] mid2_crv_clst = pm.cluster( crv.cv[2], wn=(self.mid2_T_anim, self.mid2_T_anim) )[0] end_crv_clst = pm.cluster( crv.cv[3], wn=(self.end_T_anim, self.end_T_anim) )[0] self.nodes.extend([start_crv_clst,mid1_crv_clst,mid2_crv_clst,end_crv_clst]) # # 초기위치 # self.start_up_anim.t.set( self.upVector * 10) self.end_up_anim .t.set( self.upVector * 10) self.constMe_to_end.t.set( self.aimVector * 10) pm.delete( pm.pointConstraint(self.start_T_anim, self.end_T_anim, self.constMe_to_mid) ) pm.delete( pm.pointConstraint(self.mid_T_anim, self.start_T_anim, self.mid1_T_anim) ) pm.delete( pm.pointConstraint(self.mid_T_anim, self.end_T_anim, self.mid2_T_anim) ) # # # rebuild curve for distribute # # # 커브 리빌드, 익스텐드 rbdCrv, rbd = pm.rebuildCurve( crv, ch=True, replaceOriginal=False, rebuildType=0, # uniform endKnots=1, # 0 - uniform end knots, 1 - multiple end knots keepRange=0, # 0 - reparameterize the resulting curve from 0 to 1, 1 - keep the original curve parameterization, 2 - reparameterize the result from 0 to number of spans keepControlPoints=False, keepEndPoints=True, keepTangents=True, spans=100, degree=3, tol=0.001 ) rdbCrv, extCrv = pm.extendCurve( rbdCrv, cos=0, ch=1, jn=True, rmk=True, rpo=True, distance = 1, start=0, # 0 - end, 1 - start, 2 - both extendMethod=0, # 0 - based on distance, 2 - to a 3D point extensionType=0, # 0 - Linear, 1 - Circular, 2 - Extrapolate ) rdbCrv.rename('rbdExtnd_crv') pm.parent( rdbCrv, self.doNotTouch_grp ) rdbCrv.it.set(False) # extend crv Locator crvEnd_loc = pm.spaceLocator(n='extCrvEnd_loc') pntOnCrv = pm.PyNode( pm.pointOnCurve( rdbCrv.getShape(), parameter=2.0, ch=True ) ) pntOnCrv.position >> crvEnd_loc.t pm.parent( crvEnd_loc, self.doNotTouch_grp ) self.nodes.extend([ rbdCrv, rbd,extCrv, crvEnd_loc]) # # Cluster & Constraint # # constraint Rig start_aimConst = pm.aimConstraint( self.end_T_anim, self.start_R_result, aim=self.aimVector, u=self.upVector, wu=self.startWorldUpVector, wut='object', wuo=self.start_up_anim) mid_pointConst = pm.pointConstraint( self.start_T_anim, self.end_T_anim, self.constMe_to_mid) mid_aimConst = pm.aimConstraint( self.end_T_anim, self.constMe_to_mid, aim=self.aimVector, u=self.upVector, wu=self.startWorldUpVector, wut='objectrotation', wuo=self.start_R_result) end_aimConst = pm.aimConstraint( crvEnd_loc, self.end_R_result, aim=self.aimVector, u=self.upVector, wu=self.startWorldUpVector, wut='object', wuo=self.end_up_anim) self.nodes.extend([ start_aimConst, mid_pointConst, mid_aimConst, end_aimConst ]) ctrl.aimVector >> start_aimConst.aimVector ctrl.aimVector >> mid_aimConst.aimVector ctrl.upVector >> start_aimConst.upVector ctrl.upVector >> mid_aimConst.upVector ctrl.startWorldUpVector >> start_aimConst.worldUpVector ctrl.startWorldUpVector >> mid_aimConst.worldUpVector # # Locators on Curve # unit = 1.0 / self.div locOnCrvs = [] for i in range(self.div+1): param = unit * i #xformOnCrv = pm.group( n='xformOnCrv#', em=True) xformOnCrv = pm.spaceLocator( n='xformOnCrv#') xformOnCrv.addAttr( 'parameter', sn='pr', dv=param, keyable=True ) xformOnCrv.addAttr( 'turnOnPercentage', sn='top', dv=False, at='bool', keyable=True ) xformOnCrv.addAttr( 'revRotation', sn='rot', keyable=True ) xformOnCrv.it.set(False) xformOnCrv.rename( 'xformOnCrv%02d'%i ) pntOnCrv = pm.PyNode( pm.pointOnCurve( rdbCrv.getShape(), parameter=param, ch=True ) ) pntOnCrv.turnOnPercentage.set(True) pntOnCrv.setAttr('parameter', keyable=True) pntOnCrv.setAttr('turnOnPercentage', keyable=True) pntOnCrv.rename( xformOnCrv+'_POC' ) xformOnCrv.parameter >> pntOnCrv.parameter xformOnCrv.turnOnPercentage >> pntOnCrv.turnOnPercentage pntOnCrv.position >> xformOnCrv.t locOnCrvs.append(xformOnCrv) pm.parent( locOnCrvs, self.doNotTouch_grp ) self.nodes.extend( locOnCrvs ) # # distance Rig # distNodes = [] for i in range(len(locOnCrvs)-1): dist = pm.createNode( 'distanceDimShape' ) locOnCrvs[i].worldPosition[0] >> dist.startPoint locOnCrvs[i+1].worldPosition[0] >> dist.endPoint distNodes.append( dist ) pm.parent( [dist.getParent() for dist in distNodes], self.doNotTouch_grp ) self.nodes.extend( [dist.getParent() for dist in distNodes] ) # # # Joint # # pm.select(cl=True) self.jnts = [] for i in range(self.div+1): self.jnts.append( pm.joint( n='bind%d'%i, p=self.aimVector*i ) ) if self.stretch: # 컨트롤러에 어트리뷰트 추가하고, 리깅까지 마침. #ctrl = pm.group( em=True) ctrl = self.root_grp ctrl.addAttr( 'initialDistance', multi=True, readable=True, indexMatters=False ) ctrl.addAttr( 'currentDistance', multi=True, readable=True, indexMatters=False ) ctrl.addAttr( 'scaleOutput', multi=True, readable=True, indexMatters=False ) for i in range(len(distNodes)): ctrl.initialDistance[i].set( distNodes[i].distance.get() ) distNodes[i].distance >> ctrl.currentDistance[i] md = pm.createNode('multiplyDivide') md.operation.set(2) # divide ctrl.currentDistance[i] >> md.input1X ctrl.initialDistance[i] >> md.input2X md.outputX >> ctrl.scaleOutput[i] for i in range(len( ctrl.scaleOutput.get() )): ctrl.scaleOutput[i] >> self.jnts[i].sx else: for dist, jnt in zip(distNodes, self.jnts[1:]): #if ctrl.aimAxis==1: # 아임축이 -일경우. md = pm.createNode('multiplyDivide') dist.distance >> md.input1X ctrl.aimVectorX >> md.input2X md.outputX >> jnt.tx #else: # dist.distance >> jnt.tx self.nodes.extend(self.jnts) # # # spline IK Handle # # ikHandle, endEff = pm.ikHandle(sol='ikSplineSolver', ccv=False, roc=True, pcv=False, ns=4, sj=self.jnts[0], ee=self.jnts[-1], curve=rdbCrv ) pm.parent(ikHandle, self.doNotTouch_grp ) # Enable Twist Controls : start, end Sample OBJ sampleObj_start = self.start_R_result sampleObj_end = self.end_R_result ikHandle.dTwistControlEnable.set(True) # Enable Twist Controls ikHandle.dWorldUpType.set(4) # 4:Object Rotation Up (Start/End) #sampleObj_start.xformMatrix.connect( foreArm_HDL.dWorldUpMatrix ) # << 요렇게 하면 좆됨 #sampleObj_end.xformMatrix.connect( foreArm_HDL.dWorldUpMatrixEnd ) # << 요렇게 하면 좆됨 sampleObj_start.worldMatrix >> ikHandle.dWorldUpMatrix # << 요렇게 해야함. sampleObj_end .worldMatrix >> ikHandle.dWorldUpMatrixEnd # << 요렇게 해야함. ikHandle.dWorldUpAxis. set(0) # 0:PositiveY, 1:Positive Z ikHandle.dWorldUpVector. set(self.upVector) ikHandle.dWorldUpVectorEnd.set(self.upVector) ctrl.aimAxis >> ikHandle.dWorldUpAxis ctrl.startWorldUpVector >> ikHandle.dWorldUpVector ctrl.endWorldUpVector >> ikHandle.dWorldUpVectorEnd self.nodes.extend([ikHandle,endEff])
def hairJiggle( nodes=[], prefix='jiggle', stretchable=True ): ''' update : 2015-04-27 # # 마야에서 기본으로 같은 기능을 하는 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) # get joints joints = pm.ls(sl=True, type='joint') if not joints: 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] # store current state currentToolMode = pm.currentCtx() pm.setToolTo( 'selectSuperContext' ) sel = pm.selected() # # nucleus # if not nucleus and not hairSystem: nucleus = pm.createNode( 'nucleus' ) nucleus.rename( prefix+'_nucleus' ) pm.PyNode('time1').outTime >> nucleus.currentTime # # 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 ) # # follicle 생성 # follicle = pm.createNode( 'follicle' ) follicleTr = follicle.getParent() follicleTr.rename( prefix+'_follicle' ) # follicle 위치조정 pm.delete( pm.pointConstraint( joints[0], follicleTr ) ) pm.delete( pm.orientConstraint( joints[0], follicleTr, offset=(0, 90, 0) ) ) # follicle이 조인트, parent를 따라가도록설정 # Start Joint의 Parent가 없으면 현재 Start에 페어런트 검. parent = joints[0].getParent() const = None if parent: const = pm.parentConstraint( parent, follicleTr, mo=True) else: const = pm.parentConstraint( joints[0], follicleTr, mo=True) # 기본값 follicle.restPose.set(1) # same as start follicle.startDirection.set(1) # start Curve base follicle.degree.set(2) follicle.clumpWidth.set(5) # 폴리클 디스플레이 크기 # # curve Setting # # startCurve 생성 startCurve = jntToCrv( joints, degree=3, ep=True ) startCurve.setParent( follicleTr ) startCurve.rename( prefix+'_startCurve' ) # outputCurve 생성 outputCurveShape = pm.createNode( 'nurbsCurve' ) outputCurve = outputCurveShape.getParent() outputCurve.rename( prefix+'_outputCurve' ) # # DG # 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. # # # # ikHandle # HDL, EFF = pm.ikHandle( solver='ikSplineSolver', startJoint=joints[0], endEffector=joints[-1], createCurve=False, curve=outputCurveShape, parentCurve=False ) HDL.rename( prefix+'_HDL') EFF.rename( prefix+'_EFF') # # # 그루핑 # rigGrp = pm.group(n=prefix+'_jointChainRig_grp#',em=True) rigGrp.v.set(False) pm.parent(follicleTr, HDL, outputCurve, rigGrp) # # # 스트레치 세팅 # if stretchable: # # 커브 리빌드, 익스텐드 # rdbCrv, rbd = pm.rebuildCurve( outputCurveShape, ch=True, replaceOriginal=False, rebuildType=0, # uniform endKnots=1, # 0 - uniform end knots, 1 - multiple end knots keepRange=0, # 0 - reparameterize the resulting curve from 0 to 1, 1 - keep the original curve parameterization, 2 - reparameterize the result from 0 to number of spans keepControlPoints=False, keepEndPoints=True, keepTangents=True, spans=len(joints), degree=3, tol=0.001 ) # # Locators on Curve # unit = 1.0 / (len(joints)-1) locOnCrvs = [] for i in range(len(joints)): param = unit * i xformOnCrv = pm.spaceLocator( n='xformOnCrv#') xformOnCrv.addAttr( 'parameter', sn='pr', dv=param, keyable=True ) xformOnCrv.addAttr( 'turnOnPercentage', sn='top', dv=False, at='bool', keyable=True ) xformOnCrv.addAttr( 'revRotation', sn='rot', keyable=True ) xformOnCrv.it.set(False) xformOnCrv.rename( 'xformOnCrv%02d'%i ) pntOnCrv = pm.PyNode( pm.pointOnCurve( rdbCrv.getShape(), parameter=param, ch=True ) ) pntOnCrv.turnOnPercentage.set(True) pntOnCrv.setAttr('parameter', keyable=True) pntOnCrv.setAttr('turnOnPercentage', keyable=True) pntOnCrv.rename( xformOnCrv+'_POC' ) xformOnCrv.parameter >> pntOnCrv.parameter xformOnCrv.turnOnPercentage >> pntOnCrv.turnOnPercentage pntOnCrv.position >> xformOnCrv.t locOnCrvs.append(xformOnCrv) # # distance Rig # distNodes = [] for i in range(len(locOnCrvs)-1): dist = pm.createNode( 'distanceDimShape' ) locOnCrvs[i].worldPosition[0] >> dist.startPoint locOnCrvs[i+1].worldPosition[0] >> dist.endPoint distNodes.append( dist ) # # ik핸들 커브 변경 # pm.ikHandle( HDL, e=True, curve=rdbCrv ) # # connect To Joint # for dist, jnt in zip(distNodes, joints[1:]): dist.distance >> jnt.tx # # 그루핑 # pm.parent(rdbCrv, locOnCrvs, [dist.getParent() for dist in distNodes], rigGrp) # # # restore state # pm.setToolTo( currentToolMode ) if sel: pm.select(sel) else: pm.select(cl=True)
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
def buildSplineNeck(start, end, name='', matchEndOrient=False, endOrient=util.EndOrient.TRUE_ZERO, curve=None, duplicateCurve=True, groupName='', controlSpec={} ): ''' Makes a spline with a middle control point constrained between the endpoints. .. todo:: * Might want to make the end the main control to treat it more consistently with other IK, where the main is the end of the chain. ''' if not name: name = simpleName(start) container = group(em=True, p=lib.getNodes.mainGroup(), n=name + "_controls") container.inheritsTransform.set(False) container.inheritsTransform.lock() controlChain = util.dupChain(start, end) controlChain[0].setParent(container) # If the chain is mirrored, we need to reorient to point down x so the # spline doesn't mess up when the main control rotates if controlChain[1].tx.get() < 0: # Despite aggresive zeroing of the source, the dup can still end up slightly # off zero so force it. for jnt in controlChain: jnt.r.set(0, 0, 0) joint( controlChain[0], e=True, oj='xyz', secondaryAxisOrient='yup', zso=True, ch=1) joint(controlChain[-1], e=True, oj='none') # Since the spline might shift the joints, make joints at the original pos # to constrain to. This lets us make controls agnostically since we don't. # need to maintain offset offsetChain = util.dupChain(start, end, '{0}_offset') if curve: if duplicateCurve: crv = duplicate(curve)[0] else: crv = curve mainIk, _effector = ikHandle( sol='ikSplineSolver', sj=controlChain[0], # noqa e128 ee=controlChain[-1], ccv=False, pcv=False) crv.getShape().worldSpace[0] >> mainIk.inCurve else: mainIk, _effector, crv = ikHandle( sol='ikSplineSolver', sj=controlChain[0], # noqa e128 ee=controlChain[-1], ns=1) constraints = util.constrainAtoB( util.getChain(start, end)[:-1], offsetChain[:-1], mo=False) hide(mainIk, crv, controlChain[0]) parent( mainIk, crv, container ) startJnt = duplicate( start, po=True )[0] startJnt.setParent(w=True) endJnt = duplicate( end, po=True )[0] endJnt.setParent(w=True) midCtrl = controllerShape.build( name + "_Mid", controlSpec['middle'], controllerShape.ControlType.SPLINE ) core.dagObj.lockScale(midCtrl) midPoint = pointOnCurve( crv, pr=0.5, p=True, top=True ) midChain = findClosest(midPoint, util.getChain(start, end)) core.dagObj.matchTo(midCtrl, midChain) midZero = core.dagObj.zero(midCtrl) midZero.t.set( midPoint ) midJoint = joint(None) midJoint.setParent(midCtrl) midJoint.t.set(0, 0, 0) midJoint.r.set(0, 0, 0) midZero.setParent( container ) # Setup mid controller spaces pointSpace = spaceLocator() pointSpace.rename('midPoint_{0}'.format(start)) pointSpace.setParent(container) core.dagObj.moveTo(pointSpace, midCtrl) pointConstraint( startJnt, endJnt, pointSpace, mo=True ) hide(pointSpace) space.add( midCtrl, pointSpace, spaceName='midPoint') childSpace = spaceLocator() childSpace.rename('midChild_{0}'.format(start)) childSpace.setParent(container) core.dagObj.matchTo(childSpace, midCtrl) parentConstraint( startJnt, endJnt, childSpace, mo=True ) hide(childSpace) space.add( midCtrl, childSpace, spaceName='midChild') pntRotSpace = spaceLocator() pntRotSpace.rename('midPntRot_{0}'.format(start)) pntRotSpace.setParent(container) core.dagObj.matchTo(pntRotSpace, midCtrl) pointConstraint( startJnt, endJnt, pntRotSpace, mo=True ) orientConstraint( startJnt, endJnt, pntRotSpace, mo=True ) hide(pntRotSpace) space.add( midCtrl, pntRotSpace, spaceName='midPointRot') aimer = util.midAimer(startJnt, endJnt, midCtrl) aimer.setParent(container) hide(aimer) space.add( midCtrl, aimer, spaceName='mid_aim') # Build Start and end controllers skinCluster(startJnt, endJnt, midJoint, crv, tsb=True) startCtrl = controllerShape.build( name + '_Start', controlSpec['start'], controllerShape.ControlType.SPLINE ) core.dagObj.lockScale(startCtrl) core.dagObj.matchTo( startCtrl, startJnt ) startSpace = core.dagObj.zero(startCtrl) startSpace.setParent(container) endCtrl = controllerShape.build( name + '_End', controlSpec['main'], controllerShape.ControlType.SPLINE ) core.dagObj.lockScale(endCtrl) #core.dagObj.moveTo( endCtrl, end ) #core.dagObj.zero( endCtrl ).setParent( container ) """ ORIGINAL matchEndOrient code if not matchEndOrient: core.dagObj.matchTo( endCtrl, endJnt ) else: print( 'JUST MOVING' ) core.dagObj.moveTo( endCtrl, endJnt ) core.dagObj.zero(endCtrl).setParent(container) if matchEndOrient: rot = determineClosestWorldOrient(end) endCtrl.r.set( rot ) storeTrueZero(endCtrl, rot) """ # Begin new endOrient enum code (replacing matchEndOrient) # matchEndOrient=False == TRUE_ZERO # matchEndOrient=True == JOINT if endOrient == util.EndOrient.WORLD: core.dagObj.moveTo( endCtrl, endJnt ) elif endOrient == util.EndOrient.JOINT: core.dagObj.matchTo( endCtrl, endJnt ) elif endOrient == util.EndOrient.TRUE_ZERO: core.dagObj.moveTo( endCtrl, endJnt ) core.dagObj.zero(endCtrl).setParent(container) if endOrient == util.EndOrient.TRUE_ZERO: rot = util.determineClosestWorldOrient(end) endCtrl.r.set( rot ) util.storeTrueZero(endCtrl, rot) # End new endOrient enum code util.makeStretchySpline( endCtrl, mainIk ) # Constraint to endJnt, which has the same orientation as end instead of endCtrl endJnt.setParent( endCtrl ) endConstraints = util.constrainAtoB( [end], [endJnt] ) util.driveConstraints( constraints, endConstraints ) hide( startJnt, endJnt, midJoint ) space.addWorld(endCtrl) space.add( endCtrl, start.getParent(), 'parent' ) space.add( endCtrl, startCtrl, 'start' ) space.add( startCtrl, start.getParent(), 'parent' ) startJnt.setParent( startCtrl ) orientConstraint( endCtrl, controlChain[-1], mo=True ) # ctrls = addControlsToCurve('Blah', crv) # startCtrl.setParent( ctrls[0] ) # endCtrl.setParent( ctrls[3] ) # parentConstraint( ctrls[0], midCtrl, ctrls[1], mo=True ) # parentConstraint( ctrls[3], midCtrl, ctrls[2], mo=True ) #hide( ctrls[1:3] ) # Setup matchers for easy ik switching later endMatch = util.createMatcher(endCtrl, end) endMatch.setParent(container) startMatch = util.createMatcher(startCtrl, start) startMatch.setParent(container) distances = {} jointChain = util.getChain(start, end) for j in jointChain: distances[ core.dagObj.distanceBetween(j, midCtrl) ] = j for dist, j in sorted(distances.items()): # Make a matcher here midMatch = util.createMatcher(midCtrl, j) midMatch.setParent(container) break # Setup the endControl as the leader endCtrl = nodeApi.RigController.convert(endCtrl) endCtrl.container = container endCtrl.subControl['mid'] = midCtrl endCtrl.subControl['start'] = startCtrl # Since the chain might have reversed, use the control chain for the twist axes. util.advancedTwist(controlChain[0], controlChain[1], startCtrl, endCtrl, mainIk) # Since adding the advanced twist can slightly alter things (sometimes), # put the offset joints in as the last step for ctrl, offset in zip(controlChain, offsetChain): offset.setParent(ctrl) return endCtrl, constraints
def jointChain( joints=[], prefix='chain', ctrlNum=3 ): if joints: pm.select(joints) joints = pm.ls(sl=True, type='joint') if not joints: raise if ctrlNum < 2: raise jointNum = len(joints) degree = 3 if ctrlNum == 3: degree = 2 # ============================= # # 컨트롤러 # # ============================= crv = jntToCrv(joints, degree=3, ep=True ) ctrlRbd_crv, ctrlRbd_rbd = pm.rebuildCurve( crv, ch=True, replaceOriginal=False, rebuildType=0, endKnots=1, keepRange=0, keepControlPoints=0, keepEndPoints=1, keepTangents=0, spans=ctrlNum-degree, degree=degree, tol=0.01 ) # create curve cv clusters anims = [] pm.select( ctrlRbd_crv.cv ) for cv in pm.ls(sl=True, fl=True): anims.append( pm.cluster( cv )[0] ) #anim = pm.cluster( cv, wn=(self.start_T_anim,self.start_T_anim) )[0] # # # ikHandle # HDL, EFF = pm.ikHandle( solver='ikSplineSolver', startJoint=joints[0], endEffector=joints[-1], createCurve=False, curve=ctrlRbd_crv, parentCurve=False ) HDL.rename( prefix+'_HDL') EFF.rename( prefix+'_EFF') # # # 그루핑 # rigGrp = pm.group(n=prefix+'_jointChain_grp#',em=True) rigGrp.v.set(False) pm.parent( HDL, crv, ctrlRbd_crv, rigGrp) # ============================= # # spline IK, Stretch & Distribute Joint # # ============================= # # 커브 리빌드, 익스텐드 # rdbCrv, rbd = pm.rebuildCurve( ctrlRbd_crv, ch=True, replaceOriginal=False, rebuildType=0, # uniform endKnots=1, # 0 - uniform end knots, 1 - multiple end knots keepRange=0, # 0 - reparameterize the resulting curve from 0 to 1, 1 - keep the original curve parameterization, 2 - reparameterize the result from 0 to number of spans keepControlPoints=False, keepEndPoints=True, keepTangents=True, spans=len(joints), degree=3, tol=0.001 ) # # Locators on Curve # unit = 1.0 / (len(joints)-1) locOnCrvs = [] for i in range(len(joints)): param = unit * i xformOnCrv = pm.spaceLocator( n='xformOnCrv#') xformOnCrv.addAttr( 'parameter', sn='pr', dv=param, keyable=True ) xformOnCrv.addAttr( 'turnOnPercentage', sn='top', dv=False, at='bool', keyable=True ) xformOnCrv.addAttr( 'revRotation', sn='rot', keyable=True ) xformOnCrv.it.set(False) xformOnCrv.rename( 'xformOnCrv%02d'%i ) pntOnCrv = pm.PyNode( pm.pointOnCurve( rdbCrv.getShape(), parameter=param, ch=True ) ) pntOnCrv.turnOnPercentage.set(True) pntOnCrv.setAttr('parameter', keyable=True) pntOnCrv.setAttr('turnOnPercentage', keyable=True) pntOnCrv.rename( xformOnCrv+'_POC' ) xformOnCrv.parameter >> pntOnCrv.parameter xformOnCrv.turnOnPercentage >> pntOnCrv.turnOnPercentage pntOnCrv.position >> xformOnCrv.t locOnCrvs.append(xformOnCrv) # # distance Rig # distNodes = [] for i in range(len(locOnCrvs)-1): dist = pm.createNode( 'distanceDimShape' ) locOnCrvs[i].worldPosition[0] >> dist.startPoint locOnCrvs[i+1].worldPosition[0] >> dist.endPoint distNodes.append( dist ) # # ik핸들 커브 변경 # pm.ikHandle( HDL, e=True, curve=rdbCrv ) # # connect To Joint # for dist, jnt in zip(distNodes, joints[1:]): dist.distance >> jnt.tx # # 그루핑 # pm.parent(rdbCrv, locOnCrvs, [dist.getParent() for dist in distNodes], rigGrp)
def twoPointArcRig( prefix='arc1' ): ''' 리깅된 아크 커브를 생성한다. a = createTowPointArcRig( 'arc_L' ) ''' pointA = pm.spaceLocator() pointB = pm.spaceLocator() arcCenter = pm.spaceLocator() arcCenter.it.set(False) center = pm.spaceLocator() up = pm.spaceLocator() pointA.tx.set(10) pointB.tx.set(-10) up.ty.set(5) makeArc = pm.createNode('makeTwoPointCircularArc') makeArc.radius.set(20) makeArc.directionVector.set(0,1,0) pointA.worldPosition[0] >> makeArc.pt1 pointB.worldPosition[0] >> makeArc.pt2 # upVector minus = pm.createNode( 'plusMinusAverage' ) up.worldPosition[0] >> minus.input3D[0] center.worldPosition[0] >> minus.input3D[1] minus.operation.set(2) # minus minus.output3D >> makeArc.directionVector pm.select(cl=True) crv = pm.group(em=True) crv.it.set(False) crv.addAttr('radius', keyable=True) crv.radius.set(20) crvShape = pm.createNode('nurbsCurve', p=crv) makeArc.outputCurve >> crvShape.create crv.radius >> makeArc.radius # Point On Curve Node poc = pm.PyNode( pm.pointOnCurve( crv, pr=0.5, ch=True ) ) poc.curvatureCenter >> arcCenter.t # Locator on Curve locOnCrv = pm.spaceLocator() locOnCrv.it.set(False) locOnCrv.addAttr('parameter', keyable=True, dv=0.5, min=0, max=1 ) poc.p >> locOnCrv.t poc.turnOnPercentage.set(True) locOnCrv.parameter >> poc.parameter # Group grp = pm.group( em=True ) pm.parent( locOnCrv, pointA, pointB, arcCenter, up, center, crv, grp ) # Rename pointA.rename( prefix + '_pt1') pointB.rename( prefix + '_pt2') arcCenter.rename( prefix + '_arcCenter') crv.rename( prefix + '_crv') grp.rename( prefix + '_grp') poc.rename( prefix + '_poc') makeArc.rename( prefix + '_makeArc') locOnCrv.rename( prefix + '_locOnCrv') up.rename( prefix + '_up') center.rename( prefix + '_center') # Visible center.v.set(False) up.v.set(False) arcCenter.v.set(False) return [grp, crv, locOnCrv, pointA, pointB, arcCenter, poc, up, center, makeArc ]