Example #1
0
    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
Example #3
0
    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
Example #5
0
    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
Example #6
0
    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
Example #7
0
    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
Example #8
0
    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))