def arcCheck(self): if len(self.arcPoints)>4: # if more than the maximum of 4 points have been given, determine which to use if float(int(float(len(self.arcPoints)-1)/3.0))==float(len(self.arcPoints)-1)/3.0: #divisible by 3 self.arcPoints=\ [ self.arcPoints[0], self.arcPoints[int((len(self.arcPoints)-1)/3.0)], # 1/3 self.arcPoints[int((2*len(self.arcPoints)-1)/3.0)], # 2/3 self.arcPoints[-1] ] elif float(int(float(len(self.arcPoints)-1)/2.0))==float(len(self.arcPoints)-1)/2.0: #even self.arcPoints=\ [ self.arcPoints[0], self.arcPoints[int(float(len(self.arcPoints)-1)/2.0)], # 1/2 self.arcPoints[int(float(len(self.arcPoints)-1)/2.0)], # 1/2 self.arcPoints[-1] ] else: self.arcPoints=\ [ self.arcPoints[0], self.arcPoints[int(float(len(self.arcPoints)-1)/2.0)], # 1/2- self.arcPoints[int(float(len(self.arcPoints)-1)/2.0)+1], # 1/2+ self.arcPoints[-1] ] # check to see that all the points are not on the same vector ( co-linear ) vA=vB=vC=cD=[] realArcPoints=self.arcPoints[:] mp=midPoint(self.arcPoints[0],self.arcPoints[-1]) dist=distanceBetween(self.arcPoints[0],self.arcPoints[-1]) zp=dist/1000 offsets=[[self.poleVector[0]*zp,self.poleVector[1]*zp,self.poleVector[2]*zp],(0,zp,0),(0,0,zp),(zp,0,0)] for i in range(1,10): for offset in offsets: if len(self.arcPoints)>2: vA=normalize(self.arcPoints[1][0]-self.arcPoints[0][0],self.arcPoints[1][1]-self.arcPoints[0][1],self.arcPoints[1][2]-self.arcPoints[0][2]) vB=normalize(self.arcPoints[-1][0]-self.arcPoints[1][0],self.arcPoints[-1][1]-self.arcPoints[1][1],self.arcPoints[-1][2]-self.arcPoints[1][2]) vC=normalize(self.arcPoints[-2][0]-self.arcPoints[0][0],self.arcPoints[-2][1]-self.arcPoints[0][1],self.arcPoints[-2][2]-self.arcPoints[0][2]) vD=normalize(self.arcPoints[-1][0]-self.arcPoints[-2][0],self.arcPoints[-1][1]-self.arcPoints[-2][1],self.arcPoints[-1][2]-self.arcPoints[-2][2]) if distanceBetween(vA,vB)<zp/4 or distanceBetween(vC,vD)<zp/4 or len(self.arcPoints)==2: self.arcPoints=realArcPoints[:] if len(self.arcPoints)==2: self.arcPoints=[self.arcPoints[0],[],self.arcPoints[-1]] self.arcPoints[1]=(mp[0]+offset[0]*i,mp[1]+offset[1]*i,mp[2]+offset[2]*i) else: break if distanceBetween(vA,vB)<zp/4 or distanceBetween(vC,vD)<zp/4 or len(self.arcPoints)==2: break
def __init__(self,*args,**keywords): # default options self.name='limb' self.stretch=20 self.squash=0 self.twist=True # performs auto detect self.sway=True self.switch='ik' # initial ik/fk switch state self.handleOptions=[{'type':'doubleEllipse','spin':-180},{'type':'doubleEllipse','spin':-90},{'type':'doubleEllipse'},{'type':'locator'}] self.tol=1.0 # angle tolerance for preferred angles self.parent='' self.shortNames=\ { 'n':'name', 'p':'parent', 'sp':'softParent', 'co':'controlObjects', 'ho':'handleOptions' } # attributes self.controlObjects=['','','',''] self.bindPoses=[] self.joints=[] self.group='' self.orientAxis='' self.bendAxis='' self.poleAxis='' self.ctrlJoints=[] self.handles=[] self.endEffector='' self.ikHandle='' self.jointParent='' self.jointParent='' self.originalRotations={} self.bendDirection=0 self.poleVector=[] self.poleVectorWorld=[] self.upVector=[] self.aimVector=[] self.parentSpaces=[] for k in keywords: if k in self.__dict__: exec('self.'+k+'=keywords[k]') elif k in self.shortNames: exec('self.'+self.shortNames[k]+'=keywords[k]') uniqueNames(re=True) if len(args)==0: args=mc.ls(sl=True) sel=[] for a in args: sel.extend(iterable(a)) sel=hierarchyOrder(sel) # parse options defualtHandleOptions=[{'type':'doubleEllipse','spin':-180},{'type':'doubleEllipse','spin':-90},{'type':'doubleEllipse'},{'type':'locator'}] i=len(self.handleOptions) while len(self.handleOptions)<4: self.handleOption.append(defualtHandleOptions[i]) i+=1 if isinstance(self.handleOptions,dict): self.handleOptions=[self.handleOptions,self.handleOptions,self.handleOptions] elif isIterable(self.handleOptions): if len(self.handleOptions)==0: self.handleOptions.append({}) while len(self.handleOptions)<3: self.handleOptions.append(self.handleOptions[-1]) else: self.handleOptions=[{},{},{}] self.controlObjects=iterable(self.controlObjects) self.orientAxis=self.orientAxis.lower() self.baseTwist='' self.hierarchy=[] if len(sel)>2: for j in sel[:-1]: if len(hierarchyBetween(j,sel[-1]))>len(self.hierarchy): self.hierarchy=hierarchyBetween(j,sel[-1]) closest=9e999 for s in removeAll([self.hierarchy[0],self.hierarchy[-1]],sel): if\ ( len(iterable(mc.listRelatives(self.hierarchy[0],p=True)))==0 or s in mc.listRelatives(mc.listRelatives(self.hierarchy[0],p=True)[0],c=True,type='joint') ): dist=distanceBetween(s,self.hierarchy[0]) if dist<closest: closest=dist self.baseTwist=s else: self.hierarchy=hierarchyBetween(sel[0],sel[-1]) self.bindPoses=iterable(getBindPoses(self.hierarchy)) self.joints=['','',''] if len(self.hierarchy)<3: raise Exception('There are no joints between your start and end joint. No IK created.') self.joints[0]=self.hierarchy[0] self.joints[-1]=self.hierarchy[-1] # find the orientation axis self.orientAxis='x' axisLen={'x':0,'y':0,'z':0} for j in self.hierarchy[1:]: for a in ['x','y','z']: axisLen[a]+=abs(mc.getAttr(j+'.t'+a)) if axisLen[a]>axisLen[self.orientAxis]: self.orientAxis=a # find bend joint and pole vector self.originalRotations={} for j in self.hierarchy[1:-1]: # check to see if any have a non-zero preferred angle for a in removeAll(self.orientAxis,['x','y','z']): if abs(mc.getAttr(j+'.pa'+a))>=self.tol: self.originalRotations[j+'.r'+a]=mc.getAttr(j+'.r'+a) mc.setAttr(j+'.r'+a,mc.getAttr(j+'.pa'+a)) greatestAngle=0 for j in self.hierarchy[1:-1]: jPos=mc.xform(j,q=True,ws=True,rp=True) prevJPos=mc.xform(self.hierarchy[self.hierarchy.index(j)-1],q=True,ws=True,rp=True) nextJPos=mc.xform(self.hierarchy[self.hierarchy.index(j)+1],q=True,ws=True,rp=True) vAngle=mc.angleBetween(v1=normalize(jPos[0]-prevJPos[0],jPos[1]-prevJPos[1],jPos[2]-prevJPos[2]),v2=normalize(nextJPos[0]-jPos[0],nextJPos[1]-jPos[1],jPos[2]-jPos[2]))[-1] if abs(vAngle)>greatestAngle: greatestAngle=abs(vAngle) self.joints[1]=j mp=midPoint\ ( self.hierarchy[0],self.hierarchy[-1], bias=\ ( distanceBetween(self.hierarchy[0],self.joints[1])/ (distanceBetween(self.hierarchy[0],self.joints[1])+distanceBetween(self.joints[1],self.hierarchy[-1])) ) ) bendPoint=mc.xform(self.joints[1],q=True,ws=True,rp=True) self.poleVectorWorld=normalize\ ( bendPoint[0]-mp[0], bendPoint[1]-mp[1], bendPoint[2]-mp[2] ) pmm=mc.createNode('pointMatrixMult') mc.setAttr(pmm+'.vm',True) mc.connectAttr(self.joints[1]+'.worldInverseMatrix',pmm+'.im') mc.setAttr(pmm+'.ip',*self.poleVectorWorld) self.poleVector=mc.getAttr(pmm+'.o')[0] disconnectNodes(pmm) mc.delete(pmm) greatestLength=0.0 for i in [0,1,2]: if abs(self.poleVector[i])>greatestLength and ['x','y','z'][i]!=self.orientAxis: self.poleAxis=['x','y','z'][i] greatestLength=abs(self.poleVector[i]) self.bendDirection=-abs(self.poleVector[i])/self.poleVector[i] for r in self.originalRotations: mc.setAttr(r,self.originalRotations[r]) preferredAngleWarning=False if not mc.objExists(self.joints[1]): preferredAngleWarning=True mp=midPoint(self.hierarchy[0],self.hierarchy[-1]) cd=9e999 dist=0 for j in self.hierarchy[1:-1]: dist=distanceBetween(j,mp) if dist<cd: cd=dist self.joints[1]=j self.bendAxis=removeAll(self.orientAxis,['z','y','x'])[0] if self.poleAxis=='': self.poleAxis=removeAll([self.orientAxis,self.bendAxis],['x','y','z'])[0] if self.bendAxis=='': self.bendAxis=removeAll([self.orientAxis,self.poleAxis],['x','y','z'])[0] if self.orientAxis=='': self.orientAxis=removeAll([self.bendAxis,self.poleAxis],['x','y','z'])[0] if self.poleAxis=='x': self.poleVector=[-self.bendDirection,0.0,0.0] if self.poleAxis=='y': self.poleVector=[0.0,-self.bendDirection,0.0] if self.poleAxis=='z': self.poleVector=[0.0,0.0,-self.bendDirection] if self.bendAxis=='x': self.upVector=[-self.bendDirection,0.0,0.0] if self.bendAxis=='y': self.upVector=[0.0,-self.bendDirection,0.0] if self.bendAxis=='z': self.upVector=[0.0,0.0,-self.bendDirection] if self.orientAxis=='x': self.aimVector=[self.bendDirection,0.0,0.0] if self.orientAxis=='y': self.aimVector=[0.0,self.bendDirection,0.0] if self.orientAxis=='z': self.aimVector=[0.0,0.0,self.bendDirection] if mc.objExists(self.baseTwist): conn=False for a in ['.r','.rx','.ry','.rz']: if mc.connectionInfo(self.baseTwist+a,id=True): conn=True if not conn: mc.orientConstraint(self.joints[0],self.baseTwist,sk=self.orientAxis) # load ik2Bsolver - ikRPSolver does not work well with this setup mel.eval('ik2Bsolver') self.create() if preferredAngleWarning: raise Warning('Warning: Joints are co-linear and no preferred angles were set. Results may be unpredictable.')
def __init__(self,*args,**keywords): #check to make sure unique names are used in scene uniqueNames(iterable(mc.ls(type='dagNode')),re=True) # default options self.createSurface=False # use for IK's etc. - creates a surface instead of a curve self.scaleLength=True # use for IK's etc. - compensates for scale self.stretch=-1 # maximum stretch %: 0 > Infinity self.squash=-1 # maximum squash %: 0 > 100 self.arcWeight=.5 # controls the balance of rotational control weight alloted to the end Handle vs the base Handle self.width=1 # surface width self.length=10 # only used if no arguments are passed self.parents=['',''] # create under parent or parents self.softParents=['',''] self.parentSpaces=['',''] self.names=['ArcCtrl#','arcCtrl_handle#'] # self.handleType=['locator','locator'] # see 'Handle' class - 'locator','doubleEllipse', self.handleOptions=[{},{}] # dictionaries passed on to the Handle class for options concerning placement of handles self.aim=(0,1,0) self.poleVector=(0,0,1) # if only two arc points are given, it will try to point the arc in this direction if possible # option abbreviations shortNames=\ { 'p':'parents', 'cs':'createSurface', 'pv':'poleVector', 'st':'stretch', 'sq':'squash', 'cs':'createSurface', 'n':'names', 'ho':'handleOptions', 'w':'width', 'pv':'poleVector', 'aw':'arcWeight', 'ht':'handleType', 'sp':'softParents' } if 'shortNames' in self.__dict__: # this is done so that we don't wipe out added short names in inheriting classes for sn in shortNames: self.shortNames[sn]=shortNames[sn] else: self.shortNames=shortNames for k in keywords: #get user options if k in self.shortNames: exec('self.'+self.shortNames[k]+'=keywords[k]') elif k in self.__dict__: exec('self.'+k+'=keywords[k]') #check and format options if\ ( len(iterable(self.aim))<3 or not isinstance(self.aim[0],(float,int,long)) or not isinstance(self.aim[1],(float,int,long)) or not isinstance(self.aim[2],(float,int,long)) ): self.aim=(0,1,0) if\ ( len(iterable(self.poleVector))<3 or not isinstance(self.poleVector[0],(float,int,long)) or not isinstance(self.poleVector[1],(float,int,long)) or not isinstance(self.poleVector[2],(float,int,long)) ): self.poleVector=(0,0,1) self.aim=normalize(self.aim) self.poleVector=normalize(self.poleVector) if len(iterable(self.softParents))==1: self.softParents=[iterable(self.softParents)[0],iterable(self.softParents)[0]] elif len(iterable(self.softParents))==0: self.softParents=['',''] if len(iterable(self.parents))==1: self.parents=[iterable(self.parents)[0],iterable(self.parents)[0]] elif len(iterable(self.parents))==0: self.parents=['','.'] if len(iterable(self.names))==1: self.names=[iterable(self.names)[0],iterable(self.names)[0]] if len(iterable(self.names))==0: self.names=['',''] if len(iterable(self.handleType))==1: self.handleType=[iterable(self.handleType)[0],iterable(self.handleType)[0]] if len(iterable(self.handleType))==0: self.handleType=['',''] if isinstance(self.handleOptions,dict): self.handleOptions=[self.handleOptions,self.handleOptions] if isinstance(self.handleOptions,(list,tuple)) and\ len(self.handleOptions)==1 and\ isinstance(self.handleOptions[0],dict): self.handleOptions=[self.handleOptions[0],self.handleOptions[0]] if self.stretch>=0 and self.squash<0 or self.stretch<0 and self.squash>=0:# squash & stretch come as a pair, set one to 0 if only 1 is set if self.stretch<0: self.stretch=0 if self.squash<0: self.squash=0 if not isinstance(self.poleVector,tuple): self.poleVector=tuple(self.poleVector) # attributes self.outputCurve='' self.outputNormal='' self.surface='' self.outputSurface='' self.handleShapes=[] self.curveShapes=[] self.arcPoints=[] self.handles=[] # parse arguments if len(args)==0: args=iterable(mc.ls(sl=True,fl=True)) # if no arguments are input, use selection if len(args)==0: args=[[0.0,0.0,0.0]] sel=[] for a in args: if isIterable(a) and not isinstance(a[0],(float,long,int)): sel.extend(a) else: sel.append(a) for s in sel: if isIterable(s) and isinstance(s[0],(float,long,int)) and len(s)>=3: self.arcPoints.append(s) elif isinstance(s,basestring) and mc.objExists(s): err=True if len(s.split('.'))>1: try: self.arcPoints.append(mc.pointPosition(s)) err=False except: err=True else: try: self.arcPoints.append(mc.pointPosition(s+'.rp')) err=False except: err=True if len(self.arcPoints)<2: if len(self.arcPoints)==0: self.arcPoints=[[0.0,0.0,0.0]] self.arcPoints=\ [ self.arcPoints[0], [ float(self.arcPoints[0][0])+float(self.aim[0])*self.length, float(self.arcPoints[0][1])+float(self.aim[1])*self.length, float(self.arcPoints[0][2])+float(self.aim[2])*self.length ] ] self.create()