def e2q(self, x, y, z): x = dt.radians(x) y = dt.radians(y) z = dt.radians(z) # Assuming the angles are in radians. c1 = math.cos(y / 2.0) s1 = math.sin(y / 2.0) c2 = math.cos(z / 2.0) s2 = math.sin(z / 2.0) c3 = math.cos(x / 2.0) s3 = math.sin(x / 2.0) c1c2 = c1 * c2 s1s2 = s1 * s2 qw = c1c2 * c3 - s1s2 * s3 qx = c1c2 * s3 + s1s2 * c3 qy = s1 * c2 * c3 + c1 * s2 * s3 qz = c1 * s2 * c3 - s1 * c2 * s3 q = OpenMaya.MQuaternion(qx, qy, qz, qw) return q
def e2q(self, x, y, z): x = dt.radians(x) y = dt.radians(y) z = dt.radians(z) # Assuming the angles are in radians. c1 = math.cos(y/2.0) s1 = math.sin(y/2.0) c2 = math.cos(z/2.0) s2 = math.sin(z/2.0) c3 = math.cos(x/2.0) s3 = math.sin(x/2.0) c1c2 = c1*c2 s1s2 = s1*s2 qw =c1c2*c3 - s1s2*s3 qx =c1c2*s3 + s1s2*c3 qy =s1*c2*c3 + c1*s2*s3 qz =c1*s2*c3 - s1*c2*s3 q = OpenMaya.MQuaternion(qx,qy,qz,qw) return q
def addObjects(self): """Add all the objects needed to create the component.""" self.normal = self.getNormalFromPos(self.guide.apos) self.binormal = self.getBiNormalFromPos(self.guide.apos) self.length0 = vector.getDistance( self.guide.apos[0], self.guide.apos[1]) self.length1 = vector.getDistance( self.guide.apos[1], self.guide.apos[2]) self.length2 = vector.getDistance( self.guide.apos[2], self.guide.apos[3]) # FK Controlers ----------------------------------- # *ms* set npo @ Tpose, to make the fk rotation work # best with rot order"yzx" self.fk_cns = primitive.addTransformFromPos( self.root, self.getName("fk_cns"), self.guide.apos[0]) vec_offset = ((self.guide.apos[1] - self.guide.apos[0]) * [1, 0, 0]) tpv = self.guide.apos[0] + vec_offset t = transform.getTransformLookingAt(self.guide.apos[0], self.guide.apos[1], self.normal, "xz", self.negate) # *ms* add FK isolation self.fk0_npo = primitive.addTransform( self.fk_cns, self.getName("fk0_npo"), t) t = transform.getTransformLookingAt(self.guide.apos[0], self.guide.apos[1], self.normal, "xz", self.negate) po_off = datatypes.Vector(.35 * self.length0 * self.n_factor, 0, 0) self.fk0_ctl = self.addCtl(self.fk0_npo, "fk0_ctl", t, self.color_fk, "cube", w=self.length0 * .7, h=self.size * .1, d=self.size * .1, po=po_off, tp=self.parentCtlTag) attribute.setKeyableAttributes(self.fk0_ctl) # *ms* add fk roll control Simage style po_off = datatypes.Vector(.85 * self.length0 * self.n_factor, 0, 0) self.fk0_roll_ctl = self.addCtl(self.fk0_ctl, "fk0_roll_ctl", t, self.color_fk, "cube", w=self.length0 * .3, h=self.size * .1, d=self.size * 0.1, po=po_off, tp=self.fk0_ctl) attribute.setRotOrder(self.fk0_roll_ctl, "YZX") attribute.setKeyableAttributes(self.fk0_roll_ctl, ["rx"]) self.fk0_mtx = primitive.addTransform( self.root, self.getName("fk0_mtx"), t) t = transform.setMatrixPosition(t, self.guide.apos[1]) self.fk1_ref = primitive.addTransform( self.fk0_roll_ctl, self.getName("fk1_ref"), t) self.fk1_loc = primitive.addTransform( self.root, self.getName("fk1_loc"), t) t = transform.getTransformLookingAt(self.guide.apos[1], self.guide.apos[2], self.normal, "xz", self.negate) self.fk1_npo = primitive.addTransform( self.fk1_loc, self.getName("fk1_npo"), t) po_off = datatypes.Vector(.35 * self.length1 * self.n_factor, 0, 0) self.fk1_ctl = self.addCtl(self.fk1_npo, "fk1_ctl", t, self.color_fk, "cube", w=self.length1 * .7, h=self.size * .1, d=self.size * .1, po=po_off, tp=self.fk0_roll_ctl) attribute.setKeyableAttributes(self.fk1_ctl) self.fk1_mtx = primitive.addTransform( self.fk1_ctl, self.getName("fk1_mtx"), t) po_off = datatypes.Vector(.85 * self.length1 * self.n_factor, 0, 0) self.fk1_roll_ctl = self.addCtl(self.fk1_ctl, "fk1_roll_ctl", t, self.color_fk, "cube", w=self.length1 * .3, h=self.size * .1, d=self.size * .1, po=po_off, tp=self.fk1_ctl) attribute.setRotOrder(self.fk1_roll_ctl, "XYZ") attribute.setKeyableAttributes(self.fk1_roll_ctl, ["rx"]) t = transform.getTransformLookingAt(self.guide.apos[2], self.guide.apos[3], self.normal, "xz", self.negate) # *ms* buffer object to feed into ikfk solver for hand seperation self.fk2_mtx = primitive.addTransform(self.fk1_roll_ctl, self.getName("fk2_mtx"), t) # fk2_loc is need to take the effector position + bone1 rotation t1 = transform.getTransformLookingAt(self.guide.apos[2], self.guide.apos[1], self.normal, "-xz", self.negate) self.fk2_loc = primitive.addTransform( self.root, self.getName("fk2_loc"), t1) self.fk2_npo = primitive.addTransform(self.fk2_loc, self.getName("fk2_npo"), t) po_off = datatypes.Vector(.5 * self.length2 * self.n_factor, 0, 0) self.fk2_ctl = self.addCtl(self.fk2_npo, "fk2_ctl", t, self.color_fk, "cube", w=self.length2, h=self.size * .1, d=self.size * .1, po=po_off, tp=self.fk1_roll_ctl) attribute.setKeyableAttributes(self.fk2_ctl) self.fk_ctl = [self.fk0_roll_ctl, self.fk1_mtx, self.fk2_ctl] self.fk_ctls = [self.fk0_ctl, self.fk0_roll_ctl, self.fk1_ctl, self.fk1_roll_ctl, self.fk2_ctl] for x in self.fk_ctls: attribute.setInvertMirror(x, ["tx", "ty", "tz"]) # IK Controlers ----------------------------------- self.ik_cns = primitive.addTransformFromPos( self.root, self.getName("ik_cns"), self.guide.pos["wrist"]) self.ikcns_ctl = self.addCtl( self.ik_cns, "ikcns_ctl", transform.getTransformFromPos(self.guide.pos["wrist"]), self.color_ik, "null", w=self.size * .12, tp=self.parentCtlTag) attribute.setInvertMirror(self.ikcns_ctl, ["tx", "ty", "tz"]) if self.negate: m = transform.getTransformLookingAt(self.guide.pos["wrist"], self.guide.pos["eff"], self.normal, "x-y", True) else: m = transform.getTransformLookingAt(self.guide.pos["wrist"], self.guide.pos["eff"], self.normal, "xy", False) self.ik_ctl = self.addCtl(self.ikcns_ctl, "ik_ctl", m, self.color_ik, "cube", w=self.size * .12, h=self.size * .12, d=self.size * .12, tp=self.ikcns_ctl) attribute.setKeyableAttributes(self.ik_ctl) attribute.setInvertMirror(self.ik_ctl, ["tx", "ry", "rz"]) # upv v = self.guide.apos[2] - self.guide.apos[0] v = self.normal ^ v v.normalize() v *= self.size * .5 v += self.guide.apos[1] # *ms* auto up vector ------------------------------ self.upv_cns = primitive.addTransformFromPos(self.root, self.getName("upv_cns"), self.guide.apos[0]) self.upv_auv = primitive.addTransformFromPos(self.root, self.getName("upv_auv"), self.guide.apos[0]) self.upv_mtx = primitive.addTransformFromPos(self.upv_cns, self.getName("upv_mtx"), self.guide.apos[0]) self.upv_npo = primitive.addTransformFromPos(self.upv_mtx, self.getName("upv_npo"), v) self.upv_ctl = self.addCtl(self.upv_npo, "upv_ctl", transform.getTransform(self.upv_npo), self.color_ik, "diamond", w=self.size * .12, tp=self.parentCtlTag) attribute.setKeyableAttributes(self.upv_ctl, self.t_params) attribute.setInvertMirror(self.upv_ctl, ["tx"]) # References -------------------------------------- # Calculate again the transfor for the IK ref. This way align with FK trnIK_ref = transform.getTransformLookingAt(self.guide.pos["wrist"], self.guide.pos["eff"], self.normal, "xz", self.negate) self.ik_ref = primitive.addTransform(self.ik_ctl, self.getName("ik_ref"), trnIK_ref) self.fk_ref = primitive.addTransform(self.fk_ctl[2], self.getName("fk_ref"), trnIK_ref) # Chain -------------------------------------------- # take outputs of the ikfk2bone solver self.bone0 = primitive.addLocator( self.root, self.getName("0_bone"), transform.getTransform(self.fk_ctl[0])) self.bone0_shp = self.bone0.getShape() self.bone0_shp.setAttr("localPositionX", self.n_factor * .5) self.bone0_shp.setAttr("localScale", .5, 0, 0) self.bone0.setAttr("sx", self.length0) self.bone0.setAttr("visibility", False) self.bone1 = primitive.addLocator( self.root, self.getName("1_bone"), transform.getTransform(self.fk_ctl[1])) self.bone1_shp = self.bone1.getShape() self.bone1_shp.setAttr("localPositionX", self.n_factor * .5) self.bone1_shp.setAttr("localScale", .5, 0, 0) self.bone1.setAttr("sx", self.length1) self.bone1.setAttr("visibility", False) self.ctrn_loc = primitive.addTransformFromPos(self.root, self.getName("ctrn_loc"), self.guide.apos[1]) # eff npo --- take the effector output of gear ik solver self.eff_npo = primitive.addTransformFromPos(self.root, self.getName("eff_npo"), self.guide.apos[2]) # eff loc --- take the fk ik blend result self.eff_loc = primitive.addTransformFromPos(self.eff_npo, self.getName("eff_loc"), self.guide.apos[2]) # Mid Controler ------------------------------------ self.mid_ctl = self.addCtl(self.ctrn_loc, "mid_ctl", transform.getTransform(self.ctrn_loc), self.color_ik, "sphere", w=self.size * .2, tp=self.parentCtlTag) attribute.setInvertMirror(self.mid_ctl, ["tx", "ty", "tz"]) # *ms* add elbow thickness # Roll join ref self.tws0_npo = primitive.addTransform( self.root, self.getName("tws0_npo"), transform.getTransform(self.fk_ctl[0])) self.tws0_loc = primitive.addTransform( self.tws0_npo, self.getName("tws0_loc"), transform.getTransform(self.fk_ctl[0])) self.tws0_rot = primitive.addTransform( self.tws0_loc, self.getName("tws0_rot"), transform.getTransform(self.fk_ctl[0])) self.tws1_npo = primitive.addTransform( self.ctrn_loc, self.getName("tws1_npo"), transform.getTransform(self.ctrn_loc)) self.tws1_loc = primitive.addTransform( self.tws1_npo, self.getName("tws1_loc"), transform.getTransform(self.ctrn_loc)) self.tws1_rot = primitive.addTransform( self.tws1_loc, self.getName("tws1_rot"), transform.getTransform(self.ctrn_loc)) self.tws2_loc = primitive.addTransform( self.tws1_npo, self.getName("tws2_loc"), transform.getTransform(self.ctrn_loc)) self.tws2_rot = primitive.addTransform( self.tws2_loc, self.getName("tws2_rot"), transform.getTransform(self.ctrn_loc)) self.tws3_npo = primitive.addTransform( self.root, self.getName("tws3_npo"), transform.getTransform(self.fk_ctl[2])) self.tws3_loc = primitive.addTransform( self.tws3_npo, self.getName("tws3_loc"), transform.getTransform(self.fk_ctl[2])) self.tws3_rot = primitive.addTransform( self.tws3_loc, self.getName("tws3_rot"), transform.getTransform(self.fk_ctl[2])) # Divisions ---------------------------------------- # We have at least one division at the start, the end and one for the # elbow. + 2 for elbow angle control # separate up and dn limb self.divisions = self.settings["div0"] + self.settings["div1"] + 3 + 2 self.divisions0 = self.settings["div0"] + 2 self.divisions1 = self.settings["div1"] + 2 self.div_cns = [] self.div_cnsUp = [] self.div_cnsDn = [] self.div_ctls = [] self.div_org = primitive.addTransform( self.root, self.getName("div_org"), transform.getTransform(self.root)) self.previousTag = self.parentCtlTag for i in range(self.divisions0): div_cns = primitive.addTransform( self.div_org, self.getName("div%s_loc" % i)) if self.negate: div_ctl = self.addCtl( div_cns, self.getName("div%s_ctl" % i), transform.getTransform(div_cns), self.color_fk, "square", d=self.size * .05, w=self.size * .1, po=datatypes.Vector(0, self.size * -0.05, 0), ro=datatypes.Vector(0, 0, datatypes.radians(90)), tp=self.previousTag) else: div_ctl = self.addCtl( div_cns, self.getName("div%s_ctl" % i), transform.getTransform(div_cns), self.color_fk, "square", d=self.size * .05, w=self.size * .1, po=datatypes.Vector(0, self.size * 0.05, 0), ro=datatypes.Vector(0, 0, datatypes.radians(90)), tp=self.previousTag) attribute.setKeyableAttributes(div_ctl) self.previousTag = div_ctl self.div_cns.append(div_cns) self.div_cnsUp.append(div_cns) self.jnt_pos.append([div_ctl, i]) self.div_ctls.append(div_ctl) # mid division d = self.divisions0 self.div_mid = primitive.addTransform( self.div_org, self.getName("div%s_loc" % d), transform.getTransform(self.mid_ctl)) if self.negate: self.div_mid_ctl = self.addCtl( self.div_mid, self.getName("div%s_ctl" % d), transform.getTransform(self.div_mid), self.color_fk, "square", d=self.size * .05, w=self.size * .1, po=datatypes.Vector(0, self.size * -0.05, 0), ro=datatypes.Vector(0, 0, datatypes.radians(90)), tp=self.previousTag) else: self.div_mid_ctl = self.addCtl( self.div_mid, self.getName("div%s_ctl" % d), transform.getTransform(self.div_mid), self.color_fk, "square", d=self.size * .05, w=self.size * .1, po=datatypes.Vector(0, self.size * 0.05, 0), ro=datatypes.Vector(0, 0, datatypes.radians(90)), tp=self.previousTag) attribute.setKeyableAttributes(self.div_mid_ctl) self.previousTag = div_ctl self.div_cns.append(self.div_mid) self.jnt_pos.append([self.div_mid_ctl, self.divisions0]) self.div_ctls.append(self.div_mid_ctl) # down division for i in range(self.divisions1): dd = i + self.divisions1 + 1 div_cns = primitive.addTransform( self.div_org, self.getName("div%s_loc" % dd)) if self.negate: div_ctl = self.addCtl( div_cns, self.getName("div%s_ctl" % dd), transform.getTransform(div_cns), self.color_fk, "square", d=self.size * .05, w=self.size * .1, po=datatypes.Vector(0, self.size * -0.05, 0), ro=datatypes.Vector(0, 0, datatypes.radians(90)), tp=self.previousTag) else: div_ctl = self.addCtl( div_cns, self.getName("div%s_ctl" % dd), transform.getTransform(div_cns), self.color_fk, "square", d=self.size * .05, w=self.size * .1, po=datatypes.Vector(0, self.size * 0.05, 0), ro=datatypes.Vector(0, 0, datatypes.radians(90)), tp=self.previousTag) attribute.setKeyableAttributes(div_ctl) self.previousTag = div_ctl self.div_cns.append(div_cns) self.div_cnsDn.append(div_cns) self.jnt_pos.append([div_ctl, i + self.divisions0 + 1]) self.div_ctls.append(div_ctl) # End reference ------------------------------------ # To help the deformation on the wrist self.jnt_pos.append([self.eff_loc, 'end']) # match IK FK references self.match_fk0 = self.add_match_ref(self.fk_ctl[0], self.root, "fk0_mth") self.match_fk1 = self.add_match_ref(self.fk_ctl[1], self.root, "fk1_mth") self.match_fk2 = self.add_match_ref(self.fk_ctl[2], self.ik_ctl, "fk2_mth") self.match_ik = self.add_match_ref(self.ik_ctl, self.fk2_ctl, "ik_mth") self.match_ikUpv = self.add_match_ref(self.upv_ctl, self.fk0_roll_ctl, "upv_mth") # add visual reference self.line_ref = icon.connection_display_curve( self.getName("visalRef"), [self.upv_ctl, self.mid_ctl])
def compute(self, plug, data): # Get inputs matrices ------------------------------ # Inputs Parent dh_inputP = data.inputArrayValue( gear_rollSplineKine.ctlParent ) inputsP = [] for i in range(dh_inputP.elementCount()): dh_inputP.jumpToElement(i) inputsP.append(dh_inputP.inputValue().asMatrix()) tmInP = [OpenMaya.MTransformationMatrix(m) for m in inputsP ] # Inputs dh_inputs = data.inputArrayValue( gear_rollSplineKine.inputs ) inputs = [] for i in range(dh_inputs.elementCount()): dh_inputs.jumpToElement(i) inputs.append(dh_inputs.inputValue().asMatrix()) tmIn = [OpenMaya.MTransformationMatrix(m) for m in inputs ] dh_inputsR = data.inputArrayValue( gear_rollSplineKine.inputsRoll ) inputsR = [] roll = [] for i in range(dh_inputsR.elementCount()): dh_inputsR.jumpToElement(i) inputsR.append(dh_inputsR.inputValue().asFloat()) roll.append(dt.radians(dh_inputsR.inputValue().asFloat())) # Output Parent outputParent = data.inputValue( gear_rollSplineKine.outputParent ).asMatrix() # Get inputs sliders ------------------------------- count = dh_inputs.elementCount() u = data.inputValue(gear_rollSplineKine.u).asFloat() resample = data.inputValue(gear_rollSplineKine.resample).asBool() subdiv = data.inputValue(gear_rollSplineKine.subdiv).asLong() absolute = data.inputValue(gear_rollSplineKine.absolute).asBool() if count < 1: return # Process ------------------------------------------ # Get roll, pos, tan, rot, scl pos = [] tan = [] rot = [] scl = [] for mParent, m in zip(tmInP, tmIn): # Get the roll value # roll.append(m.eulerRotation().x) # map the object to world space and get pos, tan, rot and scl # m = self.mapObjectPoseToWorldSpace(mParent, m) pos.append( m.getTranslation(OpenMaya.MSpace.kWorld) ) rot.append(mParent.rotation()) util = OpenMaya.MScriptUtil() util.createFromDouble(0.0, 0.0, 0.0) ptr = util.asDoublePtr() m.getScale(ptr, OpenMaya.MFnMatrixAttribute.kDouble) scl.append(OpenMaya.MVector(util.getDoubleArrayItem(ptr, 0), util.getDoubleArrayItem(ptr, 1), util.getDoubleArrayItem(ptr, 2))) tan.append(OpenMaya.MVector(util.getDoubleArrayItem(ptr, 0)*2.5,0,0).rotateBy(m.rotation())) modelXF = tmInP[0] # Get step and indexes # We define between wich controlers the object is to be able to # calculate the bezier 4 points front this 2 objects step = 1.0 / max(1, count-1) index1 = int(min(count-2, u/step)) index2 = index1 + 1 index1temp = index1 index2temp = index2 v = (u - step * index1) / step vtemp = v # calculate the bezier if not resample: # straight bezier solve bezierPos, xAxis = self.bezier4point(pos[index1], tan[index1], pos[index2], tan[index2], v) elif not absolute: presample=[None]*subdiv presampletan=[None]*subdiv samplelen=[0.0]*subdiv samplestep = 1.0 / (subdiv-1.0) sampleu = samplestep presample[0] = pos[index1] presampletan[0] = tan[index1] prevsample = pos[index1] overalllen = 0 for i in range(1, subdiv): p, t = self.bezier4point(pos[index1], tan[index1], pos[index2], tan[index2], sampleu) presample[i] = p presampletan[i] = t diff = p - prevsample overalllen += diff.length() samplelen[i] = overalllen prevsample = p sampleu += samplestep sampleu = 0 for i in range(subdiv-1): samplelen[i+1] = samplelen[i+1] / (overalllen+0.0) if v >= samplelen[i] and v <= samplelen[i+1]: v = (v - samplelen[i]) / (samplelen[i+1] - samplelen[i]) bezierPos = self.linearlyInterpolate(presample[i], presample[i+1], v) xAxis = self.linearlyInterpolate(presampletan[i], presampletan[i+1], v) break sampleu += samplestep else: presample=[None]*subdiv presampletan=[None]*subdiv samplelen=[0]*subdiv samplestep = 1.0 / (subdiv-1.0) sampleu = samplestep presample[0] = pos[0] presampletan[0] = tan[0] prevsample = pos[0] samplelen[0] = 0 overalllen = 0 for i in range(1,subdiv): index1 = int(min(count-2,sampleu / step)) index2 = index1+1 v = (sampleu - step * index1) / step p, t = self.bezier4point(pos[index1],tan[index1],pos[index2],tan[index2],v) presample[i] = p presampletan[i] = t diff = p - prevsample overalllen += diff.length() samplelen[i] = overalllen prevsample = p sampleu += samplestep sampleu = 0 for i in range(subdiv-1): samplelen[i+1] = samplelen[i+1] / overalllen if u >= samplelen[i] and u <= samplelen[i+1]: u = (u - samplelen[i]) / (samplelen[i+1] - samplelen[i]) bezierPos = self.linearlyInterpolate(presample[i], presample[i+1], u) xAxis = self.linearlyInterpolate(presampletan[i], presampletan[i+1], u) break sampleu += samplestep # compute the scaling (straight interpolation!) scl1 = self.linearlyInterpolate(scl[index1temp], scl[index2temp],vtemp) # compute the rotation! q = self.slerp(rot[index1temp], rot[index2temp], vtemp) yAxis = OpenMaya.MVector(0,1,0).rotateBy(q) # use directly or project the roll values! # print roll a = roll[index1temp] * (1.0 - vtemp) + roll[index2temp] * vtemp xAxis.normalize() yAxis = yAxis.rotateBy( OpenMaya.MQuaternion(xAxis.x * math.sin(a/2.0), xAxis.y * math.sin(a/2.0), xAxis.z * math.sin(a/2.0), math.cos(a/2.0))) zAxis = xAxis ^ yAxis yAxis = zAxis ^ xAxis xAxis.normalize() yAxis.normalize() zAxis.normalize() # Output ------------------------------------------- result = OpenMaya.MTransformationMatrix() # translation result.setTranslation(bezierPos, OpenMaya.MSpace.kWorld) # rotation q = self.getQuaternionFromAxes(xAxis,yAxis,zAxis) result.setRotationQuaternion(q.x, q.y, q.z, q.w) # scaling util = OpenMaya.MScriptUtil() util.createFromDouble(1, scl1.y, scl1.z) result.setScale(util.asDoublePtr(), OpenMaya.MFnMatrixAttribute.kDouble) if plug == gear_rollSplineKine.output: h = data.outputValue( gear_rollSplineKine.output ) h.setMMatrix( result.asMatrix() * outputParent.inverse() ) data.setClean( plug ) else: return OpenMaya.MStatus.kUnknownParameter return OpenMaya.MStatus.kSuccess
def compute(self, plug, data): # Get inputs matrices ------------------------------ # Inputs Parent dh_inputP = data.inputArrayValue(gear_rollSplineKine.ctlParent) inputsP = [] for i in range(dh_inputP.elementCount()): dh_inputP.jumpToElement(i) inputsP.append(dh_inputP.inputValue().asMatrix()) tmInP = [OpenMaya.MTransformationMatrix(m) for m in inputsP] # Inputs dh_inputs = data.inputArrayValue(gear_rollSplineKine.inputs) inputs = [] for i in range(dh_inputs.elementCount()): dh_inputs.jumpToElement(i) inputs.append(dh_inputs.inputValue().asMatrix()) tmIn = [OpenMaya.MTransformationMatrix(m) for m in inputs] dh_inputsR = data.inputArrayValue(gear_rollSplineKine.inputsRoll) inputsR = [] roll = [] for i in range(dh_inputsR.elementCount()): dh_inputsR.jumpToElement(i) inputsR.append(dh_inputsR.inputValue().asFloat()) roll.append(dt.radians(dh_inputsR.inputValue().asFloat())) # Output Parent outputParent = data.inputValue( gear_rollSplineKine.outputParent).asMatrix() # Get inputs sliders ------------------------------- count = dh_inputs.elementCount() u = data.inputValue(gear_rollSplineKine.u).asFloat() resample = data.inputValue(gear_rollSplineKine.resample).asBool() subdiv = data.inputValue(gear_rollSplineKine.subdiv).asLong() absolute = data.inputValue(gear_rollSplineKine.absolute).asBool() if count < 1: return # Process ------------------------------------------ # Get roll, pos, tan, rot, scl pos = [] tan = [] rot = [] scl = [] for mParent, m in zip(tmInP, tmIn): # Get the roll value # roll.append(m.eulerRotation().x) # map the object to world space and get pos, tan, rot and scl # m = self.mapObjectPoseToWorldSpace(mParent, m) pos.append(m.getTranslation(OpenMaya.MSpace.kWorld)) rot.append(mParent.rotation()) util = OpenMaya.MScriptUtil() util.createFromDouble(0.0, 0.0, 0.0) ptr = util.asDoublePtr() m.getScale(ptr, OpenMaya.MFnMatrixAttribute.kDouble) scl.append( OpenMaya.MVector(util.getDoubleArrayItem(ptr, 0), util.getDoubleArrayItem(ptr, 1), util.getDoubleArrayItem(ptr, 2))) tan.append( OpenMaya.MVector(util.getDoubleArrayItem(ptr, 0) * 2.5, 0, 0).rotateBy(m.rotation())) modelXF = tmInP[0] # Get step and indexes # We define between wich controlers the object is to be able to # calculate the bezier 4 points front this 2 objects step = 1.0 / max(1, count - 1) index1 = int(min(count - 2, u / step)) index2 = index1 + 1 index1temp = index1 index2temp = index2 v = (u - step * index1) / step vtemp = v # calculate the bezier if not resample: # straight bezier solve bezierPos, xAxis = self.bezier4point(pos[index1], tan[index1], pos[index2], tan[index2], v) elif not absolute: presample = [None] * subdiv presampletan = [None] * subdiv samplelen = [0.0] * subdiv samplestep = 1.0 / (subdiv - 1.0) sampleu = samplestep presample[0] = pos[index1] presampletan[0] = tan[index1] prevsample = pos[index1] overalllen = 0 for i in range(1, subdiv): p, t = self.bezier4point(pos[index1], tan[index1], pos[index2], tan[index2], sampleu) presample[i] = p presampletan[i] = t diff = p - prevsample overalllen += diff.length() samplelen[i] = overalllen prevsample = p sampleu += samplestep sampleu = 0 for i in range(subdiv - 1): samplelen[i + 1] = samplelen[i + 1] / (overalllen + 0.0) if v >= samplelen[i] and v <= samplelen[i + 1]: v = (v - samplelen[i]) / (samplelen[i + 1] - samplelen[i]) bezierPos = self.linearlyInterpolate( presample[i], presample[i + 1], v) xAxis = self.linearlyInterpolate(presampletan[i], presampletan[i + 1], v) break sampleu += samplestep else: presample = [None] * subdiv presampletan = [None] * subdiv samplelen = [0] * subdiv samplestep = 1.0 / (subdiv - 1.0) sampleu = samplestep presample[0] = pos[0] presampletan[0] = tan[0] prevsample = pos[0] samplelen[0] = 0 overalllen = 0 for i in range(1, subdiv): index1 = int(min(count - 2, sampleu / step)) index2 = index1 + 1 v = (sampleu - step * index1) / step p, t = self.bezier4point(pos[index1], tan[index1], pos[index2], tan[index2], v) presample[i] = p presampletan[i] = t diff = p - prevsample overalllen += diff.length() samplelen[i] = overalllen prevsample = p sampleu += samplestep sampleu = 0 for i in range(subdiv - 1): samplelen[i + 1] = samplelen[i + 1] / overalllen if u >= samplelen[i] and u <= samplelen[i + 1]: u = (u - samplelen[i]) / (samplelen[i + 1] - samplelen[i]) bezierPos = self.linearlyInterpolate( presample[i], presample[i + 1], u) xAxis = self.linearlyInterpolate(presampletan[i], presampletan[i + 1], u) break sampleu += samplestep # compute the scaling (straight interpolation!) scl1 = self.linearlyInterpolate(scl[index1temp], scl[index2temp], vtemp) # compute the rotation! q = self.slerp(rot[index1temp], rot[index2temp], vtemp) yAxis = OpenMaya.MVector(0, 1, 0).rotateBy(q) # use directly or project the roll values! # print roll a = roll[index1temp] * (1.0 - vtemp) + roll[index2temp] * vtemp xAxis.normalize() yAxis = yAxis.rotateBy( OpenMaya.MQuaternion(xAxis.x * math.sin(a / 2.0), xAxis.y * math.sin(a / 2.0), xAxis.z * math.sin(a / 2.0), math.cos(a / 2.0))) zAxis = xAxis ^ yAxis yAxis = zAxis ^ xAxis xAxis.normalize() yAxis.normalize() zAxis.normalize() # Output ------------------------------------------- result = OpenMaya.MTransformationMatrix() # translation result.setTranslation(bezierPos, OpenMaya.MSpace.kWorld) # rotation q = self.getQuaternionFromAxes(xAxis, yAxis, zAxis) result.setRotationQuaternion(q.x, q.y, q.z, q.w) # scaling util = OpenMaya.MScriptUtil() util.createFromDouble(1, scl1.y, scl1.z) result.setScale(util.asDoublePtr(), OpenMaya.MFnMatrixAttribute.kDouble) if plug == gear_rollSplineKine.output: h = data.outputValue(gear_rollSplineKine.output) h.setMMatrix(result.asMatrix() * outputParent.inverse()) data.setClean(plug) else: return OpenMaya.MStatus.kUnknownParameter return OpenMaya.MStatus.kSuccess
def compute(self, plug, data): # Get inputs matrices ------------------------------ root = data.inputValue(gear_ikfk2Bone.root).asMatrix() tmRoot = OpenMaya.MTransformationMatrix(root) ikref = data.inputValue(gear_ikfk2Bone.ikref).asMatrix() tmIkRef = OpenMaya.MTransformationMatrix(ikref) upv = data.inputValue(gear_ikfk2Bone.upv).asMatrix() tmUpV = OpenMaya.MTransformationMatrix(upv) inAparent = data.inputValue(gear_ikfk2Bone.inAparent).asMatrix() inBparent = data.inputValue(gear_ikfk2Bone.inBparent).asMatrix() inCenterparent = data.inputValue( gear_ikfk2Bone.inCenterparent).asMatrix() inEffparent = data.inputValue(gear_ikfk2Bone.inEffparent).asMatrix() fk0 = data.inputValue(gear_ikfk2Bone.fk0).asMatrix() tmFK0 = OpenMaya.MTransformationMatrix(fk0) fk1 = data.inputValue(gear_ikfk2Bone.fk1).asMatrix() tmFK1 = OpenMaya.MTransformationMatrix(fk1) fk2 = data.inputValue(gear_ikfk2Bone.fk2).asMatrix() tmFK2 = OpenMaya.MTransformationMatrix(fk2) # Get inputs sliders ------------------------------- lengthA = data.inputValue(gear_ikfk2Bone.lengthA).asFloat() lengthB = data.inputValue(gear_ikfk2Bone.lengthB).asFloat() negate = data.inputValue(gear_ikfk2Bone.negate).asBool() blend = data.inputValue(gear_ikfk2Bone.blend).asFloat() roll = dt.radians(data.inputValue(gear_ikfk2Bone.roll).asFloat()) scaleA = data.inputValue(gear_ikfk2Bone.scaleA).asFloat() scaleB = data.inputValue(gear_ikfk2Bone.scaleB).asFloat() maxstretch = data.inputValue(gear_ikfk2Bone.maxstretch).asFloat() softness = data.inputValue(gear_ikfk2Bone.softness).asFloat() slide = data.inputValue(gear_ikfk2Bone.slide).asFloat() reverse = data.inputValue(gear_ikfk2Bone.reverse).asFloat() outName = plug.name().split(".")[-1] # IK Parameters Dictionary ik = {} ik["root"] = tmRoot ik["eff"] = tmIkRef ik["upv"] = tmUpV ik["lengthA"] = lengthA ik["lengthB"] = lengthB ik["negate"] = negate ik["roll"] = roll ik["scaleA"] = scaleA ik["scaleB"] = scaleB ik["maxstretch"] = maxstretch ik["softness"] = softness ik["slide"] = slide ik["reverse"] = reverse # FK Parameters Dictionary fk = {} fk["root"] = tmRoot fk["bone1"] = tmFK0 fk["bone2"] = tmFK1 fk["eff"] = tmFK2 fk["lengthA"] = lengthA fk["lengthB"] = lengthB fk["negate"] = negate # Process # for optimization if blend == 0.0: result = self.getFKTransform(fk, outName) elif blend == 1.0: result = self.getIKTransform(ik, outName) else: # here is where the blending happens! ikbone1 = self.getIKTransform(ik, "outA") ikbone2 = self.getIKTransform(ik, "outB") ikeff = self.getIKTransform(ik, "outEff") fkbone1 = self.getFKTransform(fk, "outA") fkbone2 = self.getFKTransform(fk, "outB") fkeff = self.getFKTransform(fk, "outEff") # remove scale to avoid shearing issue # This is not necessary in Softimage because the scaling hierarchy is not computed the same way. util = OpenMaya.MScriptUtil() util.createFromDouble(1, 1, 1) ikbone1.setScale(util.asDoublePtr(), OpenMaya.MFnMatrixAttribute.kDouble) ikbone2.setScale(util.asDoublePtr(), OpenMaya.MFnMatrixAttribute.kDouble) ikeff.setScale(util.asDoublePtr(), OpenMaya.MFnMatrixAttribute.kDouble) fkbone1.setScale(util.asDoublePtr(), OpenMaya.MFnMatrixAttribute.kDouble) fkbone2.setScale(util.asDoublePtr(), OpenMaya.MFnMatrixAttribute.kDouble) fkeff.setScale(util.asDoublePtr(), OpenMaya.MFnMatrixAttribute.kDouble) # map the secondary transforms from global to local ikeff = self.mapWorldPoseToObjectSpace(ikbone2, ikeff) fkeff = self.mapWorldPoseToObjectSpace(fkbone2, fkeff) ikbone2 = self.mapWorldPoseToObjectSpace(ikbone1, ikbone2) fkbone2 = self.mapWorldPoseToObjectSpace(fkbone1, fkbone2) # now blend them! fk["bone1"] = self.interpolateTransform(fkbone1, ikbone1, blend) fk["bone2"] = self.interpolateTransform(fkbone2, ikbone2, blend) fk["eff"] = self.interpolateTransform(fkeff, ikeff, blend) # now map the local transform back to global! fk["bone2"] = self.mapObjectPoseToWorldSpace( fk["bone1"], fk["bone2"]) fk["eff"] = self.mapObjectPoseToWorldSpace(fk["bone2"], fk["eff"]) # calculate the result based on that result = self.getFKTransform(fk, outName) # Output if plug == gear_ikfk2Bone.outA: h_outA = data.outputValue(gear_ikfk2Bone.outA) h_outA.setMMatrix(result.asMatrix() * inAparent.inverse()) data.setClean(plug) elif plug == gear_ikfk2Bone.outB: h_outB = data.outputValue(gear_ikfk2Bone.outB) h_outB.setMMatrix(result.asMatrix() * inBparent.inverse()) data.setClean(plug) elif plug == gear_ikfk2Bone.outCenter: h_outC = data.outputValue(gear_ikfk2Bone.outCenter) h_outC.setMMatrix(result.asMatrix() * inCenterparent.inverse()) data.setClean(plug) elif plug == gear_ikfk2Bone.outEff: h_outE = data.outputValue(gear_ikfk2Bone.outEff) h_outE.setMMatrix(result.asMatrix() * inEffparent.inverse()) data.setClean(plug) else: return OpenMaya.MStatus.kUnknownParameter return OpenMaya.MStatus.kSuccess
def compute(self, plug, data): # Get inputs matrices ------------------------------ root = data.inputValue( gear_ikfk2Bone.root ).asMatrix() tmRoot = OpenMaya.MTransformationMatrix(root) ikref = data.inputValue( gear_ikfk2Bone.ikref ).asMatrix() tmIkRef = OpenMaya.MTransformationMatrix(ikref) upv = data.inputValue( gear_ikfk2Bone.upv ).asMatrix() tmUpV = OpenMaya.MTransformationMatrix(upv) inAparent = data.inputValue( gear_ikfk2Bone.inAparent ).asMatrix() inBparent = data.inputValue( gear_ikfk2Bone.inBparent ).asMatrix() inCenterparent = data.inputValue( gear_ikfk2Bone.inCenterparent ).asMatrix() inEffparent = data.inputValue( gear_ikfk2Bone.inEffparent ).asMatrix() fk0 = data.inputValue( gear_ikfk2Bone.fk0 ).asMatrix() tmFK0 = OpenMaya.MTransformationMatrix(fk0) fk1 = data.inputValue( gear_ikfk2Bone.fk1 ).asMatrix() tmFK1 = OpenMaya.MTransformationMatrix(fk1) fk2 = data.inputValue( gear_ikfk2Bone.fk2 ).asMatrix() tmFK2 = OpenMaya.MTransformationMatrix(fk2) # Get inputs sliders ------------------------------- lengthA = data.inputValue(gear_ikfk2Bone.lengthA).asFloat() lengthB = data.inputValue(gear_ikfk2Bone.lengthB).asFloat() negate = data.inputValue(gear_ikfk2Bone.negate).asBool() blend = data.inputValue(gear_ikfk2Bone.blend).asFloat() roll = dt.radians(data.inputValue(gear_ikfk2Bone.roll).asFloat()) scaleA = data.inputValue(gear_ikfk2Bone.scaleA).asFloat() scaleB = data.inputValue(gear_ikfk2Bone.scaleB).asFloat() maxstretch = data.inputValue(gear_ikfk2Bone.maxstretch).asFloat() softness = data.inputValue(gear_ikfk2Bone.softness).asFloat() slide = data.inputValue(gear_ikfk2Bone.slide).asFloat() reverse = data.inputValue(gear_ikfk2Bone.reverse).asFloat() outName = plug.name().split(".")[-1] # IK Parameters Dictionary ik = {} ik["root"] = tmRoot ik["eff"] = tmIkRef ik["upv"] = tmUpV ik["lengthA"] = lengthA ik["lengthB"] = lengthB ik["negate"] = negate ik["roll"] = roll ik["scaleA"] = scaleA ik["scaleB"] = scaleB ik["maxstretch"] = maxstretch ik["softness"] = softness ik["slide"] = slide ik["reverse"] = reverse # FK Parameters Dictionary fk = {} fk["root"] = tmRoot fk["bone1"] = tmFK0 fk["bone2"] = tmFK1 fk["eff"] = tmFK2 fk["lengthA"] = lengthA fk["lengthB"] = lengthB fk["negate"] = negate # Process # for optimization if blend == 0.0: result = self.getFKTransform(fk, outName) elif blend == 1.0: result = self.getIKTransform(ik, outName) else: # here is where the blending happens! ikbone1 = self.getIKTransform(ik, "outA") ikbone2 = self.getIKTransform(ik, "outB") ikeff = self.getIKTransform(ik, "outEff") fkbone1 = self.getFKTransform(fk, "outA") fkbone2 = self.getFKTransform(fk, "outB") fkeff = self.getFKTransform(fk, "outEff") # remove scale to avoid shearing issue # This is not necessary in Softimage because the scaling hierarchy is not computed the same way. util = OpenMaya.MScriptUtil() util.createFromDouble(1,1,1) ikbone1.setScale(util.asDoublePtr(), OpenMaya.MFnMatrixAttribute.kDouble) ikbone2.setScale(util.asDoublePtr(), OpenMaya.MFnMatrixAttribute.kDouble) ikeff.setScale(util.asDoublePtr(), OpenMaya.MFnMatrixAttribute.kDouble) fkbone1.setScale(util.asDoublePtr(), OpenMaya.MFnMatrixAttribute.kDouble) fkbone2.setScale(util.asDoublePtr(), OpenMaya.MFnMatrixAttribute.kDouble) fkeff.setScale(util.asDoublePtr(), OpenMaya.MFnMatrixAttribute.kDouble) # map the secondary transforms from global to local ikeff = self.mapWorldPoseToObjectSpace(ikbone2, ikeff) fkeff = self.mapWorldPoseToObjectSpace(fkbone2, fkeff) ikbone2 = self.mapWorldPoseToObjectSpace(ikbone1, ikbone2) fkbone2 = self.mapWorldPoseToObjectSpace(fkbone1, fkbone2) # now blend them! fk["bone1"] = self.interpolateTransform(fkbone1, ikbone1, blend) fk["bone2"] = self.interpolateTransform(fkbone2, ikbone2, blend) fk["eff"] = self.interpolateTransform(fkeff, ikeff, blend) # now map the local transform back to global! fk["bone2"] = self.mapObjectPoseToWorldSpace(fk["bone1"], fk["bone2"]) fk["eff"] = self.mapObjectPoseToWorldSpace(fk["bone2"], fk["eff"]) # calculate the result based on that result = self.getFKTransform(fk, outName) # Output if plug == gear_ikfk2Bone.outA: h_outA = data.outputValue( gear_ikfk2Bone.outA ) h_outA.setMMatrix( result.asMatrix() * inAparent.inverse() ) data.setClean( plug ) elif plug == gear_ikfk2Bone.outB: h_outB = data.outputValue( gear_ikfk2Bone.outB ) h_outB.setMMatrix( result.asMatrix() * inBparent.inverse() ) data.setClean( plug ) elif plug == gear_ikfk2Bone.outCenter: h_outC = data.outputValue( gear_ikfk2Bone.outCenter ) h_outC.setMMatrix( result.asMatrix() * inCenterparent.inverse() ) data.setClean( plug ) elif plug == gear_ikfk2Bone.outEff: h_outE = data.outputValue( gear_ikfk2Bone.outEff ) h_outE.setMMatrix( result.asMatrix() * inEffparent.inverse() ) data.setClean( plug ) else: return OpenMaya.MStatus.kUnknownParameter return OpenMaya.MStatus.kSuccess
def addObjects(self): self.normal = self.getNormalFromPos(self.guide.apos) self.binormal = self.getBiNormalFromPos(self.guide.apos) self.length0 = vec.getDistance(self.guide.apos[0], self.guide.apos[1]) self.length1 = vec.getDistance(self.guide.apos[1], self.guide.apos[2]) self.length2 = vec.getDistance(self.guide.apos[2], self.guide.apos[3]) # FK Controlers ----------------------------------- # *ms* set npo @ Tpose, to make the fk rotation work best with rot order"yzx" self.fk_cns = pri.addTransformFromPos(self.root, self.getName("fk_cns"), self.guide.apos[0]) tpv = self.guide.apos[0] + ((self.guide.apos[1] - self.guide.apos[0])*[0,1,0]) t = tra.getTransformLookingAt(self.guide.apos[0], tpv, self.normal, "xz", self.negate) # *ms* add FK isolation self.fk0_npo = pri.addTransform(self.fk_cns, self.getName("fk0_npo"), t) t = tra.getTransformLookingAt(self.guide.apos[0], self.guide.apos[1], self.normal, "xz", self.negate) self.fk0_ctl = self.addCtl(self.fk0_npo, "fk0_ctl", t, self.color_fk, "cube", w=self.length0*.7, h=self.size*.1, d=self.size*.1, po=dt.Vector(.35*self.length0*self.n_factor,0,0), tp=self.parentCtlTag) att.setKeyableAttributes(self.fk0_ctl) # *ms* add fk roll control Simage style self.fk0_roll_ctl = self.addCtl(self.fk0_ctl, "fk0_roll_ctl", t, self.color_fk, "cube", w=self.length0*.3, h=self.size*.1, d=self.size*.1, po=dt.Vector(.85*self.length0*self.n_factor,0,0), tp=self.fk0_ctl) att.setKeyableAttributes(self.fk0_roll_ctl) self.fk0_mtx = pri.addTransform(self.root, self.getName("fk0_mtx"), t) t = tra.setMatrixPosition(t, self.guide.apos[1]) self.fk1_ref = pri.addTransform(self.fk0_roll_ctl, self.getName("fk1_ref"), t) self.fk1_loc = pri.addTransform(self.root, self.getName("fk1_loc"), t) t = tra.getTransformLookingAt(self.guide.apos[1], self.guide.apos[2], self.normal, "xz", self.negate) self.fk1_npo = pri.addTransform(self.fk1_loc, self.getName("fk1_npo"), t) self.fk1_ctl = self.addCtl(self.fk1_npo, "fk1_ctl", t, self.color_fk, "cube", w=self.length1*.7, h=self.size*.1, d=self.size*.1, po=dt.Vector(.35*self.length1*self.n_factor,0,0), tp=self.fk0_roll_ctl) att.setKeyableAttributes(self.fk1_ctl) self.fk1_mtx = pri.addTransform(self.fk1_ctl, self.getName("fk1_mtx"), t) self.fk1_roll_ctl = self.addCtl(self.fk1_ctl, "fk1_roll_ctl", t, self.color_fk, "cube", w=self.length1*.3, h=self.size*.1, d=self.size*.1, po=dt.Vector(.85*self.length1*self.n_factor,0,0), tp=self.fk1_ctl) att.setKeyableAttributes(self.fk1_roll_ctl) # t = tra.getTransformFromPos(self.guide.pos["ankle"]) # *ms* buffer object to feed into ikfk solver for foot seperation t= tra.getTransformLookingAt(self.guide.apos[2], self.guide.apos[3], self.normal, "z-x", negate=False) self.fk2_mtx = pri.addTransform(self.fk1_roll_ctl, self.getName("fk2_mtx"), t) # fk2_loc is need to take the effector position + bone1 rotation # fk2_npo should get offset rotation from fk2_mtx t= tra.getTransformLookingAt(self.guide.apos[2], self.guide.apos[1], self.normal, "-xz", self.negate) self.fk2_loc = pri.addTransform(self.root, self.getName("fk2_loc"), t) t = tra.getTransformLookingAt(self.guide.apos[2], self.guide.apos[3], self.normal, "xz", self.negate) self.fk2_npo = pri.addTransform(self.fk2_loc, self.getName("fk2_npo"), t) self.fk2_ctl = self.addCtl(self.fk2_npo, "fk2_ctl", t, self.color_fk, "cube", w=self.length2, h=self.size*.1, d=self.size*.1, po=dt.Vector(.5*self.length2*self.n_factor,0,0), tp=self.fk1_roll_ctl) att.setKeyableAttributes(self.fk2_ctl) self.fk_ctl = [self.fk0_roll_ctl, self.fk1_ctl, self.fk2_ctl] self.fk_ctls = [self.fk0_ctl,self.fk0_roll_ctl, self.fk1_ctl, self.fk1_roll_ctl, self.fk2_ctl] for x in self.fk_ctls: att.setInvertMirror(x, ["tx", "ty", "tz"]) # att.setInvertMirror(self.fk0_ctl, ["tx", "ty", "tz"]) self.ctrn_loc = pri.addTransformFromPos(self.root, self.getName("ctrn_loc"), self.guide.apos[1]) # eff npo --- take the effector output of gear ik solver self.eff_npo = pri.addTransformFromPos(self.root, self.getName("eff_npo"), self.guide.apos[2]) # eff loc --- take the fk ik blend result self.eff_loc = pri.addTransformFromPos(self.eff_npo, self.getName("eff_loc"), self.guide.apos[2]) # tws_ref t = tra.getRotationFromAxis(dt.Vector(0,-1,0), self.normal, "xz", self.negate) t = tra.setMatrixPosition(t, self.guide.pos["ankle"]) self.tws_ref = pri.addTransform(self.eff_loc, self.getName("tws_ref"), t) # Mid Controler ------------------------------------ self.mid_ctl = self.addCtl(self.ctrn_loc, "mid_ctl", tra.getTransform(self.ctrn_loc), self.color_ik, "sphere", w=self.size*.2, tp=self.parentCtlTag) att.setInvertMirror(self.mid_ctl, ["tx", "ty", "tz"]) # *ms* add knee thickness # IK Controlers ----------------------------------- self.ik_cns = pri.addTransformFromPos(self.root, self.getName("ik_cns"), self.guide.pos["ankle"]) self.ikcns_ctl = self.addCtl(self.ik_cns, "ikcns_ctl", tra.getTransformFromPos(self.guide.pos["ankle"]), self.color_ik, "null", w=self.size*.12, tp=self.mid_ctl) att.setInvertMirror(self.ikcns_ctl, ["tx"]) m = tra.getTransformFromPos(self.guide.pos["ankle"]) self.ik_ctl = self.addCtl(self.ikcns_ctl, "ik_ctl", m, self.color_ik, "cube", w=self.size*.12, h=self.size*.12, d=self.size*.12, tp=self.ikcns_ctl) att.setKeyableAttributes(self.ik_ctl) # att.setRotOrder(self.ik_ctl, "XZY") att.setInvertMirror(self.ik_ctl, ["tx", "ry", "rz"]) # upv v = self.guide.apos[2] - self.guide.apos[0] v = self.normal ^ v v.normalize() v *= self.size*.5 v += self.guide.apos[1] # *ms* auto up vector ------------------------------ self.upv_cns = pri.addTransformFromPos(self.root, self.getName("upv_cns"), self.guide.apos[0]) self.upv_auv = pri.addTransformFromPos(self.root, self.getName("upv_auv"), self.guide.apos[0]) self.upv_mtx = pri.addTransformFromPos(self.upv_cns, self.getName("upv_mtx"), self.guide.apos[0]) self.upv_npo = pri.addTransformFromPos(self.upv_mtx, self.getName("upv_npo"), v) self.upv_ctl = self.addCtl(self.upv_npo, "upv_ctl", tra.getTransform(self.upv_npo), self.color_ik, "diamond", w=self.size*.12, tp=self.ik_ctl) att.setKeyableAttributes(self.upv_ctl, self.t_params) att.setInvertMirror(self.upv_ctl, ["tx"]) # References -------------------------------------- # Calculate again the transfor for the IK ref. This way align with FK self.ik_ref = pri.addTransform(self.ik_ctl, self.getName("ik_ref"), tra.getTransform(self.ik_ctl)) self.fk_ref = pri.addTransform(self.fk_ctl[2], self.getName("fk_ref"), tra.getTransform(self.ik_ctl)) # auto up vector foot solver self.upv1_auv = pri.addTransform(self.ik_ref, self.getName("upv1_auv"), tra.getTransform(self.ik_ctl)) self.upv2_auv = pri.addTransform(self.upv1_auv, self.getName("upv2_auv"), tra.getTransform(self.ik_ctl)) self.upv2_auv.setAttr("tz",1) # Chain -------------------------------------------- # take outputs of the ikfk2bone solver self.bone0 = pri.addLocator(self.root, self.getName("0_bone"), tra.getTransform(self.fk_ctl[0])) self.bone0_shp = self.bone0.getShape() self.bone0_shp.setAttr("localPositionX", self.n_factor*.5) self.bone0_shp.setAttr("localScale", .5, 0, 0) self.bone0.setAttr("sx", self.length0) self.bone0.setAttr("visibility", False) self.bone1 = pri.addLocator(self.root, self.getName("1_bone"), tra.getTransform(self.fk_ctl[1])) self.bone1_shp = self.bone1.getShape() self.bone1_shp.setAttr("localPositionX", self.n_factor*.5) self.bone1_shp.setAttr("localScale", .5, 0, 0) self.bone1.setAttr("sx", self.length1) self.bone1.setAttr("visibility", False) #Roll join ref self.tws0_npo = pri.addTransform(self.root, self.getName("tws0_npo"), tra.getTransform(self.fk_ctl[0])) self.tws0_loc = pri.addTransform(self.tws0_npo, self.getName("tws0_loc"), tra.getTransform(self.fk_ctl[0])) self.tws0_rot = pri.addTransform(self.tws0_loc, self.getName("tws0_rot"), tra.getTransform(self.fk_ctl[0])) self.tws1_npo = pri.addTransform(self.ctrn_loc, self.getName("tws1_npo"), tra.getTransform(self.ctrn_loc)) self.tws1_loc = pri.addTransform(self.tws1_npo, self.getName("tws1_loc"), tra.getTransform(self.ctrn_loc)) self.tws1_rot = pri.addTransform(self.tws1_loc, self.getName("tws1_rot"), tra.getTransform(self.ctrn_loc)) self.tws2_loc = pri.addTransform(self.tws1_npo, self.getName("tws2_loc"), tra.getTransform(self.ctrn_loc)) self.tws2_rot = pri.addTransform(self.tws2_loc, self.getName("tws2_rot"), tra.getTransform(self.ctrn_loc)) # self.tws3_npo = pri.addTransform(self.root, self.getName("tws3_npo"), tra.getTransform(self.fk_ctl[2])) # self.tws3_loc = pri.addTransform(self.tws3_npo, self.getName("tws3_loc"), tra.getTransform(self.fk_ctl[2])) # self.tws3_rot = pri.addTransform(self.tws3_loc, self.getName("tws3_rot"), tra.getTransform(self.fk_ctl[2])) t = t = tra.getTransformLookingAt(self.guide.apos[2], self.guide.apos[1], self.normal, "-xz", self.negate) self.tws3_npo = pri.addTransform(self.root, self.getName("tws3_npo"), t) self.tws3_loc = pri.addTransform(self.tws3_npo, self.getName("tws3_loc"), t) self.tws3_rot = pri.addTransform(self.tws3_loc, self.getName("tws3_rot"), t) # Divisions ---------------------------------------- # We have at least one division at the start, the end and one for the knee. + 2 for knee angle control # separate up and dn limb self.divisions = self.settings["div0"] + self.settings["div1"] + 3 + 2 self.divisions0 = self.settings["div0"] +2 self.divisions1 = self.settings["div1"] +2 self.div_cns = [] self.div_cnsUp = [] self.div_cnsDn = [] self.div_ctls = [] self.div_org = pri.addTransform(self.root, self.getName("div_org"), tra.getTransform(self.root)) self.previousCtlTag = self.parentCtlTag for i in range(self.divisions0): div_cns = pri.addTransform(self.div_org, self.getName("div%s_loc" % i)) if self.negate: div_ctl = self.addCtl(div_cns, self.getName("div%s_ctl" % i), tra.getTransform(div_cns), self.color_fk, "square",d=self.size*.05,w=self.size*.1,po=dt.Vector(0,self.size*-0.05,0),ro=dt.Vector(0,0,dt.radians(90)), tp=self.previousCtlTag) else: div_ctl = self.addCtl(div_cns, self.getName("div%s_ctl" % i), tra.getTransform(div_cns), self.color_fk, "square",d=self.size*.05,w=self.size*.1,po=dt.Vector(0,self.size*0.05,0),ro=dt.Vector(0,0,dt.radians(90)), tp=self.previousCtlTag) self.previousCtlTag = div_ctl self.div_cns.append(div_cns) self.div_cnsUp.append(div_cns) self.jnt_pos.append([div_ctl,i]) self.div_ctls.append(div_ctl) # mid division d = self.divisions0 self.div_mid = pri.addTransform(self.div_org, self.getName("div%s_loc" % d), tra.getTransform(self.mid_ctl)) if self.negate: self.div_mid_ctl = self.addCtl(self.div_mid, self.getName("div%s_ctl" % d), tra.getTransform(self.div_mid), self.color_fk, "square",d=self.size*.05, w=self.size*.1,po=dt.Vector(0,self.size*-0.05,0), ro=dt.Vector(0,0,dt.radians(90)), tp=self.previousCtlTag) else: self.div_mid_ctl = self.addCtl(self.div_mid, self.getName("div%s_ctl" % d), tra.getTransform(self.div_mid), self.color_fk, "square",d=self.size*.05, w=self.size*.1,po=dt.Vector(0,self.size*0.05,0), ro=dt.Vector(0,0,dt.radians(90)), tp=self.previousCtlTag) self.previousCtlTag = div_ctl self.div_cns.append(self.div_mid) self.jnt_pos.append([self.div_mid_ctl,self.divisions0]) self.div_ctls.append(self.div_mid_ctl) # down division for i in range(self.divisions1): dd = i +self.divisions1+1 div_cns = pri.addTransform(self.div_org, self.getName("div%s_loc" % dd)) if self.negate: div_ctl = self.addCtl(div_cns, self.getName("div%s_ctl" % dd), tra.getTransform(div_cns), self.color_fk, "square",d=self.size*.05, w=self.size*.1,po=dt.Vector(0,self.size*-0.05,0),ro=dt.Vector(0,0,dt.radians(90)), tp=self.previousCtlTag) else: div_ctl = self.addCtl(div_cns, self.getName("div%s_ctl" % dd), tra.getTransform(div_cns), self.color_fk, "square",d=self.size*.05, w=self.size*.1,po=dt.Vector(0,self.size*0.05,0),ro=dt.Vector(0,0,dt.radians(90)), tp=self.previousCtlTag) self.previousCtlTag = div_ctl self.div_cns.append(div_cns) self.div_cnsDn.append(div_cns) self.jnt_pos.append([div_ctl,i+self.divisions0+1]) self.div_ctls.append(div_ctl) # End reference ------------------------------------ # To help the deformation on the ankle self.jnt_pos.append([self.eff_loc, 'end']) #match IK FK references self.match_fk0 = pri.addTransform(self.root, self.getName("fk0_mth"), tra.getTransform(self.fk_ctl[0])) self.match_fk1 = pri.addTransform(self.root, self.getName("fk1_mth"), tra.getTransform(self.fk_ctl[1])) self.match_fk2 = pri.addTransform(self.ik_ref, self.getName("fk2_mth"), tra.getTransform(self.fk_ctl[2])) self.match_ik = pri.addTransform(self.fk2_ctl, self.getName("ik_mth"), tra.getTransform(self.ik_ctl)) self.match_ikUpv = pri.addTransform(self.fk0_roll_ctl, self.getName("upv_mth"), tra.getTransform(self.upv_ctl))