def getTransposedVector(v, position0, position1, inverse=False): v0 = XSIMath.CreateVector3() v0.Sub(position0[1], position0[0]) v0.NormalizeInPlace() v1 = XSIMath.CreateVector3() v1.Sub(position1[1], position1[0]) v1.NormalizeInPlace() ra = v0.Angle(v1) if inverse: ra = -ra axis = XSIMath.CreateVector3() #axis.Cross(v, v0) axis.Cross(v0, v1) r = XSIMath.CreateRotation() r.SetFromAxisAngle(axis, ra) vector = XSIMath.CreateVector3() vector.MulByRotation(v, r) # Check if the rotation has been set in the right order ra2 = (math.pi * .5) - v1.Angle(vector) r.SetFromAxisAngle(axis, -ra2) vector.MulByRotationInPlace(r) return vector
def switchToFk(self): # Match Rotation tra.matchGlobalTransform(self.fk0, self.jnt0, False, True, True) tra.matchGlobalTransform(self.fk1, self.jnt1, False, True, True) # Scale self.scale.Value = (self.length0 + self.length1) / self.rest # Switch to FK self.blend.Value = 0 if self.isleg: x = XSIMath.CreateVector3(0, 0, 1) y = XSIMath.CreateVector3(0, 1, 0) if self.negate: x.NegateInPlace() y.NegateInPlace() x.MulByRotationInPlace( self.ik.Kinematics.Global.Transform.Rotation) y.MulByRotationInPlace( self.ik.Kinematics.Global.Transform.Rotation) t = self.ik.Kinematics.Global.Transform t.SetRotation(tra.getRotationFromAxis(x, y, "xy")) self.fk2.Kinematics.Global.Transform = t else: tra.matchGlobalTransform(self.fk2, self.ik, False, True, True)
def addObjects(self): self.root = self.addRoot() self.locs = self.addLocMulti("#_loc", self.root) centers = [self.root] centers.extend(self.locs) self.dispcrv = self.addDispCurve("crv", centers) # Heel and pivots vHeel = XSIMath.CreateVector3(self.root.Kinematics.Global.PosX.Value, 0, self.root.Kinematics.Global.PosZ.Value) vLeftPivot = XSIMath.CreateVector3( self.root.Kinematics.Global.PosX.Value + .3, 0, self.root.Kinematics.Global.PosZ.Value) vRightPivot = XSIMath.CreateVector3( self.root.Kinematics.Global.PosX.Value - .3, 0, self.root.Kinematics.Global.PosZ.Value) self.heel = self.addLoc("heel", self.root, vHeel) self.outpivot = self.addLoc("outpivot", self.root, vLeftPivot) self.inpivot = self.addLoc("inpivot", self.root, vRightPivot) self.dispcrv = self.addDispCurve( "1", [self.root, self.heel, self.outpivot, self.heel, self.inpivot])
def __init__(self, t=XSIMath.CreateTransform()): self.transform = t self.x = XSIMath.CreateVector3(1, 0, 0) self.y = XSIMath.CreateVector3(0, 1, 0) self.z = XSIMath.CreateVector3(0, 0, 1) self.x.MulByRotationInPlace(t.Rotation) self.y.MulByRotationInPlace(t.Rotation) self.z.MulByRotationInPlace(t.Rotation)
def getDistanceToAxe(pos, axe_pos0, axe_pos1): axe = XSIMath.CreateVector3() axe.Sub(axe_pos1, axe_pos0) hyp = XSIMath.CreateVector3() hyp.Sub(pos, axe_pos0) a = axe.Angle(hyp) distance = trigo_adj(hyp.Length(), a) return distance
def getPlaneBiNormal(v0, v1, v2): normal = getPlaneNormal(v0, v1, v2) vector0 = XSIMath.CreateVector3() vector0.Sub(v1, v0) biNormal = XSIMath.CreateVector3() biNormal.Cross(normal, vector0) biNormal.NormalizeInPlace() return biNormal
def getOrthocentreDistances(v0, v1, v2): axe = XSIMath.CreateVector3() axe.Sub(v2, v0) hyp = XSIMath.CreateVector3() hyp.Sub(v1, v0) a = axe.Angle(hyp) distanceA = trigo_opp(hyp.Length(), a) distanceB = axe.Length() - distanceA return distanceA, distanceB
def addCubeChain(parent, name, positions, normal, negate=False, size=1, color=[0,0,0]): # Name if "#" in name: name = name.replace("#", "%s") else: name += "%s" # Draw bones = [] for i in range(len(positions)-1): v0 = positions[i-1] v1 = positions[i] v2 = positions[i+1] # Normal Offset if i > 0: normal = vec.getTransposedVector(normal, [v0, v1], [v1, v2]) t = tra.getTransformLookingAt(v1, v2, normal, "xy", negate) # Cube Offset d = vec.getDistance(v1, v2) offset = XSIMath.CreateVector3(d*.5, 0, 0) if negate: offset.NegateInPlace() # Draw bone = icon.cube(parent, name%i, d, size, size, color, t, offset) bones.append(bone) parent = bone return bones
def getClosestGlobalTransform(position, crv, subcurve=0, tan_axis="x", upv_axis="y", normal=XSIMath.CreateVector3(0, 1, 0)): crv_geo = crv.ActivePrimitive.Geometry crv_sub = crv_geo.Curves(subcurve) crv_tra = crv.Kinematics.Global.Transform pos = XSIMath.MapWorldPositionToObjectSpace(crv_tra, position) rtn = crv_geo.GetClosestCurvePosition2(pos) u = rtn[2] pos = rtn[3] pos = XSIMath.MapObjectPositionToWorldSpace(crv_tra, pos) tan = crv_sub.EvaluatePosition(u)[1] r = crv_tra.Rotation r.InvertInPlace() tan.MulByRotationInPlace(r) tan.AddInPlace(pos) t = tra.getTransformLookingAt(pos, tan, normal, tan_axis + upv_axis, False) return t
def addOptionsValues(self): # Convert color sliders to list for s in ["R_", "L_", "C_"]: self.values[s + "color_fk"] = [ self.values[s + "color_fk_r"], self.values[s + "color_fk_g"], self.values[s + "color_fk_b"] ] self.values[s + "color_ik"] = [ self.values[s + "color_ik_r"], self.values[s + "color_ik_g"], self.values[s + "color_ik_b"] ] # When not wip, some options are forced if self.values["mode"] == 0: self.values["setHidden"] = True self.values["setUnselectable"] = True self.values["setDeformers"] = True self.values["setGeometries"] = True self.values["popUpControls"] = False self.values["isolateResult"] = False # Get rig size to adapt size of object to the scale of the character maximum = 1 v = XSIMath.CreateVector3() for comp in self.components.values(): for pos in comp.apos: d = vec.getDistance(v, pos) maximum = max(d, maximum) self.values["size"] = max(maximum * .05, .1)
def pickPositionMulti(message="Pick position", logWarning=True, minimum=1, maximum=-1): pickedPositions = [] while True: rtn = xsi.PickPosition(message, message) if not rtn.Value("ButtonPressed"): break v = XSIMath.CreateVector3(rtn("PosX"), rtn("PosY"), rtn("PosZ")) pickedPositions.append(v) if addHelpers: null = pri.addNullFromPos(xsi.ActiveSceneRoot, "temp_0", v) pri.setNullDisplay(null, 1, .5, 2, 0, 0, 0, .5, .5, .5, [0, 1, 0]) helpers.Add(null) if maximum > 0 and len(pickedPositions) >= maximum: break if len(pickedPositions) < minimum: if logWarning: xsi.LogMessage("Pick Session Aborded", c.siWarning) return False return pickedPositions
def addBoneFromPos(parent, name, position=XSIMath.CreateVector3(), length=1): t = XSIMath.CreateTransform() t.SetTranslation(position) bone = addBone(parent, name, t, length) return bone
def addNullFromPos(parent, name, position=XSIMath.CreateVector3(), size=1, color=[0,0,0]): t = XSIMath.CreateTransform() t.SetTranslation(position) null = addNull(parent, name, t, size, color) return null
def getPlaneNormal(v0, v1, v2): vector0 = XSIMath.CreateVector3() vector1 = XSIMath.CreateVector3() vector0.Sub(v1, v0) vector1.Sub(v2, v0) vector0.NormalizeInPlace() vector1.NormalizeInPlace() normal = XSIMath.CreateVector3() normal.Cross(vector1, vector0) normal.NormalizeInPlace() return normal
def linearlyInterpolate(v0, v1, blend=.5): vector = XSIMath.CreateVector3() vector.Sub(v1, v0) vector.ScaleInPlace(blend) vector.AddInPlace(v0) return vector
def getOrthocentre(v0, v1, v2): axe = XSIMath.CreateVector3() axe.Sub(v2, v0) hyp = XSIMath.CreateVector3() hyp.Sub(v1, v0) a = axe.Angle(hyp) distance = trigo_opp(hyp.Length(), a) axe.NormalizeInPlace() axe.ScaleInPlace(distance) axe.AddInPlace(v0) return axe
def gear_SmoothShapeOp_Update(ctxt): # Inputs ----------------------------------------------- shape = ctxt.GetInputValue(0, 0, 0) geo = ctxt.GetInputValue(1, 0, 0).Geometry cls = ctxt.GetInputValue(2, 0, 0) neighbor_depth = ctxt.GetParameterValue("NeighbourDepth") blend = ctxt.GetParameterValue("Blend") # Process ---------------------------------------------- shape_tuple = shape.Elements.Array shape_array = [ shape_tuple[j][i] for i in range(len(shape_tuple[0])) for j in range(len(shape_tuple)) ] points = cls.Elements.Array vSmoothShape = XSIMath.CreateVector3() vOriShape = XSIMath.CreateVector3() for i in points: vertex = geo.Vertices(i) cNghbVertices = vertex.NeighborVertices(neighbor_depth) vSmoothShape.Set(0, 0, 0) vOriShape.Set(shape_array[i * 3 + 0], shape_array[i * 3 + 1], shape_array[i * 3 + 2]) for oVtx in cNghbVertices: index = oVtx.Index vSmoothShape.X += shape_array[index * 3 + 0] vSmoothShape.Y += shape_array[index * 3 + 1] vSmoothShape.Z += shape_array[index * 3 + 2] vSmoothShape.ScaleInPlace(blend / cNghbVertices.Count) vOriShape.ScaleInPlace(1 - blend) shape_array[i * 3 + 0] = vSmoothShape.X + vOriShape.X shape_array[i * 3 + 1] = vSmoothShape.Y + vOriShape.Y shape_array[i * 3 + 2] = vSmoothShape.Z + vOriShape.Z # Output ----------------------------------------------- Out = ctxt.OutputTarget Out.Elements.Array = shape_array
def lipVector(X, Y, Z, vectorMultiply): x = X * vectorMultiply y = Y * vectorMultiply z = Z * vectorMultiply vLip = XSIMath.CreateVector3( self.tongueT.Kinematics.Global.PosX.Value + x, self.tongueT.Kinematics.Global.PosY.Value + y, self.tongueT.Kinematics.Global.PosZ.Value + z) return vLip
def addObjects(self): self.root = self.addRoot() self.locs = self.addLocMulti("#_loc", self.root, False) vTemp = XSIMath.CreateVector3(self.root.Kinematics.Global.PosX.Value , self.root.Kinematics.Global.PosY.Value +2, self.root.Kinematics.Global.PosZ.Value ) self.upVector = self.addLoc("upVector", self.root, vTemp ) vTemp = XSIMath.CreateVector3(self.root.Kinematics.Global.PosX.Value , self.root.Kinematics.Global.PosY.Value , self.root.Kinematics.Global.PosZ.Value +2 ) self.direction = self.addLoc("direction", self.root, vTemp ) centers = [self.direction, self.root, self.upVector] self.dispcrv = self.addDispCurve("crvUp", centers) self.blade = self.addBlade("blade", self.root, self.upVector) centers = [] centers.extend(self.locs) self.dispcrv = self.addDispCurve("crv", centers)
def pickPosition(message="Pick position", logWarning=True): rtn = xsi.PickPosition(message, message) if rtn("ButtonPressed") == 0: if logWarning: xsi.LogMessage("Pick Session Aborded", c.siWarning) return False position = XSIMath.CreateVector3(rtn("PosX"), rtn("PosY"), rtn("PosZ")) return position
def add2DChain(parent, name, positions, normal=None, negate=False, size=1, alignRoot=False): if size < 0.05: size = 0.05 # Compute Normal -------- if normal is None: if len(positions) >= 3: normal = vector.computePlaneNormal(positions[0], positions[1], positions[2]) else: normal = XSIMath.CreateVector3(0, 0, -1) # Draw ------------------- root = parent.Add2DChain(positions[0], positions[1], normal, c.si2DChainNormalRadian) for i in range(len(positions) - 2): root.AddBone(positions[i + 2]) xChain = Chain(root, name) # Negative Scaling ------- for bone in xChain.bones: bone.size.Value = size if negate: bone.axisz = 180 #xsi.SetNeutralPose(bone) if negate: xChain.bones[0].Properties("kinematic chain").Parameters( "effori_offz").Value = 180 # Display ---------------- xChain.root.Size = size * .25 xChain.eff.Size = size * .125 # !!! This can be trouble !!! # !!! OUT OF FOCUS BUG !!! # Using this command gives weird result when the focus is not on XSI # xsi.AlignRootToFirstBone(root) if alignRoot: alignRootToFirstBone(xChain) return xChain
def getTransformLookingAt(position, lookat, normal, axis="xy", negate=False): a = XSIMath.CreateVector3() a.Sub(lookat, position) r = getRotationFromAxis(a, normal, axis, negate) t = XSIMath.CreateTransform() t.SetTranslation(position) t.SetRotation(r) return t
def getBladeBiNormalFromXml(xml_def): xNurbsCurveList = xsixmldom.NurbsCurveList(xml_def) t = xNurbsCurveList.globalTransform p = xNurbsCurveList.getPointArray() points = [] for i in range(3): v = XSIMath.CreateVector3(p[i * 3 + 0], p[i * 3 + 1], p[i * 3 + 2]) points.append(XSIMath.MapObjectPositionToWorldSpace(t, v)) normal = getPlaneBiNormal(points[0], points[1], points[2]) return normal
def rotateVectorAlongAxis(v, axis, a=0): # Angle as to be in radians sa = math.sin(a / 2.0) ca = math.cos(a / 2.0) q1 = XSIMath.CreateQuaternion(0, v.X, v.Y, v.Z) q2 = XSIMath.CreateQuaternion(ca, axis.X * sa, axis.Y * sa, axis.Z * sa) q2n = XSIMath.CreateQuaternion(ca, -axis.X * sa, -axis.Y * sa, -axis.Z * sa) q = XSIMath.CreateQuaternion() q.Mul(q2, q1) q.MulInPlace(q2n) vector = XSIMath.CreateVector3(q.X, q.Y, q.Z) return vector
def addObjects(self): t = tra.getTransformLookingAt(self.guide.pos["root"], self.guide.pos["lookat"], self.y_axis, "zy") # Direction cns self.dir_cns = pri.addNull(self.root, self.getName("dir_cns"), t, self.size * .1) self.addToGroup(self.dir_cns, "hidden") upv_pos = XSIMath.CreateVector3(0, 1, 0) upv_pos.MulByTransformationInPlace(t) self.upv_cns = pri.addNullFromPos(self.root, self.getName("upv_cns"), upv_pos, self.size * .1) self.addToGroup(self.upv_cns, "hidden") # IK Controler self.ik_cns = pri.addNull( self.root, "ik_cns", tra.getTransformFromPosition(self.guide.pos["lookat"]), self.size * .1) self.addToGroup(self.ik_cns, "hidden") self.ik_ctl = self.addCtl(self.ik_cns, "ik_ctl", tra.getTransformFromPosition( self.guide.pos["lookat"]), self.color_ik, "cross", h=self.size * .5) par.setKeyableParameters(self.ik_ctl, self.t_params) # FK Controler self.fk_ctl = self.addCtl(self.dir_cns, "fk_ctl", t, self.color_fk, "arrow", h=self.size * .5) xsi.SetNeutralPose(self.fk_ctl, c.siTrn) par.setKeyableParameters(self.fk_ctl, self.r_params) # par.addLocalParamToCollection(self.inv_params, self.fk_ctl, ["posx", "posy", "posz"]) self.addShadow(self.fk_ctl, 0)
def getRotationFromAxis(in_a, in_b, axis="xy", negate=False): a = XSIMath.CreateVector3(in_a.X, in_a.Y, in_a.Z) b = XSIMath.CreateVector3(in_b.X, in_b.Y, in_b.Z) c = XSIMath.CreateVector3() x = XSIMath.CreateVector3() y = XSIMath.CreateVector3() z = XSIMath.CreateVector3() if negate: a.NegateInPlace() a.NormalizeInPlace() c.Cross(a, b) c.NormalizeInPlace() b.Cross(c, a) b.NormalizeInPlace() if axis == "xy": x = a y = b z = c elif axis == "xz": x = a z = b y.Negate(c) elif axis == "yx": y = a x = b z.Negate(c) elif axis == "yz": y = a z = b x = c elif axis == "zx": z = a x = b y = c elif axis == "zy": z = a y = b x.Negate(c) else: gear.log("Invalid Input", gear.sev_error) return r = XSIMath.CreateRotation() r.SetFromXYZAxes(x, y, z) return r
def addObjects(self): self.normal = self.getNormalFromPos(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 ------------------------------------ t = tra.getTransformLookingAt(self.guide.apos[0], self.guide.apos[1], self.normal, "xz", self.negate) self.fk0_ctl = self.addCtl(self.root, "fk0_ctl", t, self.color_fk, "cube", h=self.size*.1, w=1, d=self.size*.1, po=XSIMath.CreateVector3(.5*self.n_factor,0,0)) self.fk0_ctl.Parameters("SclX").Value = self.length0 tra.setRefPose(self.fk0_ctl, [-90,0,0], self.negate) xsi.SetNeutralPose(self.fk0_ctl, c.siSRT) par.setKeyableParameters(self.fk0_ctl) par.addLocalParamToCollection(self.inv_params, self.fk0_ctl, ["posx", "posy", "posz"]) t = tra.getTransformLookingAt(self.guide.apos[1], self.guide.apos[2], self.normal, "xz", self.negate) self.fk1_ctl = self.addCtl(self.fk0_ctl, "fk1_ctl", t, self.color_fk, "cube", h=self.size*.1, w=1, d=self.size*.1, po=XSIMath.CreateVector3(.5*self.n_factor,0,0)) self.fk1_ctl.Parameters("SclX").Value = self.length1/self.length0 xsi.SetNeutralPose(self.fk1_ctl, c.siST) par.setKeyableParameters(self.fk1_ctl) par.addLocalParamToCollection(self.inv_params, self.fk1_ctl, ["posx", "posy", "posz"]) t = tra.getTransformLookingAt(self.guide.apos[2], self.guide.apos[3], self.normal, "xz", self.negate) self.fk2_ctl = self.addCtl(self.fk1_ctl, "fk2_ctl", t, self.color_fk, "cube", h=self.size*.1, w=self.length2, d=self.size*.1, po=XSIMath.CreateVector3(self.length2*.5*self.n_factor,0,0)) xsi.SetNeutralPose(self.fk2_ctl, c.siST) par.setKeyableParameters(self.fk2_ctl) par.addLocalParamToCollection(self.inv_params, self.fk2_ctl, ["posx", "posy", "posz"]) # IK Controlers ------------------------------------ self.ik_cns = pri.addNullFromPos(self.root, self.getName("ik_cns"), self.guide.apos[2], self.size*.02) self.addToGroup(self.ik_cns, "hidden") self.ikcns_ctl = self.addCtl(self.ik_cns, "ikcns_ctl", self.ik_cns.Kinematics.Global.Transform, self.color_ik, "null", h=self.size*.2) par.setKeyableParameters(self.ikcns_ctl) par.addLocalParamToCollection(self.inv_params, self.ikcns_ctl, ["posx", "rotx", "rotz"]) t = tra.getTransformLookingAt(self.guide.apos[2], self.guide.apos[3], self.normal, "xz", self.negate) self.ik_ctl = self.addCtl(self.ikcns_ctl, "ik_ctl", t, self.color_ik, "cube", h=self.size*.12, w=self.length2, d=self.size*.12, po=XSIMath.CreateVector3(self.length2*.5*self.n_factor,0,0)) tra.setRefPose(self.ik_ctl, [-90,0,0], self.negate) par.setKeyableParameters(self.ik_ctl) par.addLocalParamToCollection(self.inv_params, self.ik_ctl, ["posx"]) v = XSIMath.CreateVector3() v.Sub(self.guide.apos[2], self.guide.apos[0]) v.Cross(self.normal, v) v.NormalizeInPlace() v.ScaleInPlace(self.size * .5) v.AddInPlace(self.guide.apos[1]) self.upv_cns = pri.addNullFromPos(self.root, self.getName("upv_cns"), v, self.size*.02) self.addToGroup(self.upv_cns, "hidden") self.upv_ctl = self.addCtl(self.upv_cns, "upv_ctl", self.upv_cns.Kinematics.Global.Transform, self.color_ik, "leash", h=self.size*.05, ap=self.guide.apos[1]) par.setKeyableParameters(self.upv_ctl, self.t_params) par.addLocalParamToCollection(self.inv_params, self.upv_ctl, ["posx"]) # Chain -------------------------------------------- self.bone0 = pri.addNull(self.root, self.getName("0_jnt"), self.fk0_ctl.Kinematics.Global.Transform) pri.setNullDisplay(self.bone0, 0, 1, 4, self.n_factor*.5, 0, 0, 1, self.size*.01, self.size*.01) self.bone0.Kinematics.Global.Parameters("sclx").Value = self.length0 self.bone1 = pri.addNull(self.bone0, self.getName("1_jnt"), self.fk1_ctl.Kinematics.Global.Transform) pri.setNullDisplay(self.bone1, 0, 1, 4, self.n_factor*.5, 0, 0, 1, self.size*.01, self.size*.01) self.bone1.Kinematics.Global.Parameters("sclx").Value = self.length1 self.ctrn_loc = pri.addNullFromPos(self.bone0, self.getName("ctrn_loc"), self.guide.apos[1], self.size*.05) self.eff_loc = pri.addNullFromPos(self.root, self.getName("eff_loc"), self.guide.apos[2], self.size*.05) self.addToGroup([self.bone0, self.bone1, self.ctrn_loc, self.eff_loc], "hidden") # Mid Controler ------------------------------------ self.mid_ctl = self.addCtl(self.ctrn_loc, "mid_ctl", self.ctrn_loc.Kinematics.Global.Transform, self.color_ik, "sphere", h=self.size*.05) par.addLocalParamToCollection(self.inv_params, self.mid_ctl, ["posx", "posy", "posz"]) # Membrane ----------------------------------------- self.memb_loc = pri.addNull(self.mid_ctl, self.getName("memb_loc"), self.mid_ctl.Kinematics.Global.Transform, self.size*.02) self.memb_crv = cur.addCnsCurve(self.memb_loc, self.getName("memb_crv"), [self.root, self.memb_loc, self.eff_loc], False, 3) # Twist references --------------------------------- t = tra.getFilteredTransform(self.fk0_ctl.Kinematics.Global.Transform, True, True, False) self.tws0_loc = pri.addNull(self.root, self.getName("tws0_loc"), t, self.size*.05) self.tws0_rot = pri.addNull(self.tws0_loc, self.getName("tws0_rot"), t) pri.setNullDisplay(self.tws0_rot, 0, self.size*.05, 2, 0, 0, 0, self.size*.01) self.tws1_loc = pri.addNull(self.ctrn_loc, self.getName("tws1_loc"), self.ctrn_loc.Kinematics.Global.Transform, self.size*.05) self.tws1_rot = pri.addNull(self.tws1_loc, self.getName("tws1_rot"), self.ctrn_loc.Kinematics.Global.Transform) pri.setNullDisplay(self.tws1_rot, 0, self.size*.05, 2, 0, 0, 0, self.size*.01) t = tra.getFilteredTransform(self.bone1.Kinematics.Global.Transform, True, True, False) t.SetTranslation(self.guide.apos[2]) self.tws2_loc = pri.addNull(self.bone1, self.getName("tws2_loc"), t, self.size*.05) self.tws2_rot = pri.addNull(self.tws2_loc, self.getName("tws2_rot"),t) self.tws2_rot.Kinematics.Global.Parameters("SclX").Value = .001 pri.setNullDisplay(self.tws2_rot, 0, self.size*.05, 2, 0, 0, 0, self.size*.01) self.addToGroup([self.tws0_loc, self.tws0_rot, self.tws1_loc, self.tws1_rot, self.tws2_loc, self.tws2_rot], "hidden") # End reference ------------------------------------ t = tra.getFilteredTransform(self.tws2_rot.Kinematics.Global.Transform, True, True, False) self.end_ref = pri.addNull(self.tws2_rot, self.getName("end_ref"), t, self.size*.2) self.addToGroup(self.end_ref, "hidden") self.addShadow(self.end_ref, "end") # Divisions ---------------------------------------- # We have at least one division at the start, the end and one for the elbow. self.divisions = self.settings["div0"] + self.settings["div1"] + 3 self.div_cns = [] for i in range(self.divisions): div_cns = pri.addNull(self.tws0_loc, self.getName("div%s_loc"%i), XSIMath.CreateTransform()) pri.setNullDisplay(div_cns, 1, self.size*.02, 10, 0, 0, 0, 1, 1, 2) self.addToGroup(div_cns, "hidden") self.div_cns.append(div_cns) self.addShadow(div_cns, i)
def switchToIk(self): # Get the distance between Root and effector and compare it to bones total length to define if the chain is bend or not vRootEff = XSIMath.CreateVector3() vRootEff.Sub(self.jnt0.kinematics.Global.Transform.Translation, self.ik.kinematics.Global.Transform.Translation) # We get an approximation of the length otherwise it's sometimes tricky to compare distance r = 100000 dRootEffLength = round((vRootEff.Length() * r)) / r dBonesLength = round(((self.length0 + self.length1) * r)) / r # xsi.MatchTransform(self.ik, self.eff, c.siRT, None) # tra.matchGlobalTransform(self.eff, self.ik, True, True, False) tra.matchGlobalTransform(self.ik, self.fk2, True, True, True) self.blend.Value = 1 # tra.matchGlobalTransform(self.fk2, self.ik, False, True, False) # Compute Roll if dRootEffLength < dBonesLength: # Get Vectors to built the plane vFKChain0 = XSIMath.CreateVector3() vIKChain0 = XSIMath.CreateVector3() vRootEff = XSIMath.CreateVector3() vFKChain0.Sub(self.fk0.kinematics.Global.Transform.Translation, self.fk1.kinematics.Global.Transform.Translation) vIKChain0.Sub(self.jnt0.kinematics.Global.Transform.Translation, self.jnt1.kinematics.Global.Transform.Translation) vRootEff.Sub(self.jnt0.kinematics.Global.Transform.Translation, self.ik.kinematics.Global.Transform.Translation) # vFKChain0.NormalizeInPlace() # vIKChain0.NormalizeInPlace() # vRootEff.NormalizeInPlace() # Get Plane's Normal vNormFKPlane = XSIMath.CreateVector3() vNormIKPlane = XSIMath.CreateVector3() vNormFKPlane.Cross(vFKChain0, vRootEff) vNormIKPlane.Cross(vIKChain0, vRootEff) # vNormFKPlane.NormalizeInPlace() # vNormIKPlane.NormalizeInPlace() # Get the Angle between the two planess dAngle = XSIMath.RadiansToDegrees(vNormFKPlane.Angle(vNormIKPlane)) # Check if we have to remove or add the angle vCrossPlane = XSIMath.CreateVector3() vCrossPlane.Cross(vNormFKPlane, vNormIKPlane) # vCrossPlane.NormalizeInPlace() dDirectionDot = vCrossPlane.Dot(vRootEff) # Set the new roll Value a = self.roll.Value + (dDirectionDot / abs(dDirectionDot)) * dAngle # Set the angle in a -180 / 180 range if abs(a) > 180: a = a % ((-a / abs(a)) * 360) # [OLD WAY ]Set the new roll Value -- # Check if the bone is negated or not ## dNegate = self.jnt1.kinematics.Local.posx.Value + self.jnt1.kinematics.Local.nposx.Value #dNegate = 1 # oldAngle = self.roll.Value # if (dDirectionDot * dNegate) < 0: # newAngle = oldAngle - dAngle # else: # newAngle = oldAngle + dAngle # if newAngle > 180: # newAngle -= 360 # elif newAngle < -180: # newAngle += 360 # [END OLD WAY ] ------------------- self.roll.Value = a # Match Scale Value # We remove Soft distances self.softik.Value = 0 if dRootEffLength > dBonesLength: if self.scale.Value > self.maxstretch.Value: self.maxstretch.Value = self.scale.Value self.scale.Value = 1 if self.isleg: z = XSIMath.CreateVector3(1, 0, 0) y = XSIMath.CreateVector3(0, 1, 0) if self.negate: z.NegateInPlace() y.NegateInPlace() z.MulByRotationInPlace( self.fk2.Kinematics.Global.Transform.Rotation) y.MulByRotationInPlace( self.fk2.Kinematics.Global.Transform.Rotation) t = self.fk2.Kinematics.Global.Transform t.SetRotation(tra.getRotationFromAxis(z, y, "zy")) self.ik.Kinematics.Global.Transform = t else: tra.matchGlobalTransform(self.ik, self.fk2, False, True, True)
def getDistance(v0, v1): distance = XSIMath.CreateVector3() distance.Sub(v0, v1) return distance.Length()
class MainComponent(object): steps = ["Objects", "Properties", "Operators", "Connect", "Finalize"] local_params = ("posx", "posy", "posz", "rotx", "roty", "rotz", "rotorder", "sclx", "scly", "sclz") t_params = ("posx", "posy", "posz") r_params = ("rotx", "roty", "rotz", "rotorder") s_params = ("sclx", "scly", "sclz") tr_params = ("posx", "posy", "posz", "rotx", "roty", "rotz", "rotorder") rs_params = ("rotx", "roty", "rotz", "rotorder", "sclx", "scly", "sclz") x_axis = XSIMath.CreateVector3(1, 0, 0) y_axis = XSIMath.CreateVector3(0, 1, 0) z_axis = XSIMath.CreateVector3(0, 0, 1) # ===================================================== ## Init Method. # @param self # @param rig Rig - The parent Rig of this component. # @param guide ComponentGuide - The guide for this component. def __init__(self, rig, guide): # -------------------------------------------------- # Main Objects self.rig = rig self.guide = guide self.options = self.rig.options self.model = self.rig.model self.settings = self.guide.values self.name = self.settings["comp_name"] self.side = self.settings["comp_side"] self.index = self.settings["comp_index"] # -------------------------------------------------- # Shortcut to useful settings self.size = self.guide.size self.color_fk = self.options[self.side + "_color_fk"] self.color_ik = self.options[self.side + "_color_ik"] self.negate = self.side == "R" if self.negate: self.n_sign = "-" self.n_factor = -1 else: self.n_sign = "" self.n_factor = 1 # -------------------------------------------------- # Builder init self.groups = {} ## Dictionary of groups self.controlers = [] ## List of all the controlers of the component self.inv_params = XSIFactory.CreateObject("XSI.Collection") if not self.settings["set_ctl_grp"] or (self.settings["set_ctl_grp"] and self.settings["ctl_grp"] == ""): self.settings["ctl_grp"] = "01" # -------------------------------------------------- # Property init self.anim_layout = ppg.PPGLayout() self.anim_logic = ppg.PPGLogic() self.setup_layout = ppg.PPGLayout() self.setup_logic = ppg.PPGLogic() self.ui = None # -------------------------------------------------- # Connector init self.connections = {} self.connections["standard"] = self.connect_standard self.relatives = {} # -------------------------------------------------- # Step self.stepMethods = [ eval("self.step_0%s" % i) for i in range(len(self.steps)) ] # ===================================================== # BUILDING STEP # ===================================================== ## Step 00. Initial Hierarchy, create objects and set the connection relation. # @param self def step_00(self): self.initialHierarchy() self.addObjects() self.setRelation() return ## Step 01. Get the properties host, create parameters and set layout and logic. # @param self def step_01(self): self.getHost() self.addParameters() self.addLayout() self.addLogic() self.setUI() return ## Step 02. Apply all the operators. # @param self def step_02(self): self.addOperators() return ## Step 03. Connect the component to the rest of the rig. # @param self def step_03(self): self.initConnector() self.addConnection() self.connect() self.postConnect() return ## Step 04. Finalize the component. # @param self def step_04(self): self.finalize() return ## NOT YET AVAILABLE def step_05(self): self.addPostSkin() return # ===================================================== # OBJECTS # ===================================================== ## Build the initial hierarchy of the component.\n # Add the root and if needed the shadow root # @param self def initialHierarchy(self): # Root ------------------------------- self.root = pri.addNullFromPos(self.model, self.getName("root"), self.guide.pos["root"], self.options["size"] * .1) self.addToGroup(self.root, "hidden") # Shd -------------------------------- if self.options["shadowRig"]: self.shd_org = self.rig.shd_org.AddNull(self.getName("shd_org")) self.addToGroup(self.shd_org, "hidden") ## Add all the objects needed to create the component.\n # REIMPLEMENT. This method should be reimplemented in each component.\n # Try not to apply any constraint, operator, or expression in here. Just X3DObjects. # @param self def addObjects(self): return ## Add the object in a collection for later group creation # @param self # @param objs Single or List of X3DObject - object to put in group # @param names Single or List of String - names of the groups to create def addToGroup(self, objects, names=["hidden"]): if not isinstance(names, list): names = [names] if not isinstance(objects, list): objects = [objects] for name in names: if name not in self.groups.keys(): self.groups[name] = [] self.groups[name].extend(objects) def addToCtlGroup(self, objects, names=None): if names is None: names = [self.settings["ctl_grp"]] elif not isinstance(names, list): names = [names] if not isinstance(objects, list): objects = [objects] for name in names: name = "controlers_" + name if name not in self.groups.keys(): self.groups[name] = [] self.groups[name].extend(objects) self.controlers.extend(objects) def addShadow(self, obj, name): if self.options["shadowRig"]: shd = pri.addImplicite(self.shd_org, "Cube", self.getName(str(name) + "_shd"), obj.Kinematics.Global.Transform, self.options["size"] * .15) shd.Kinematics.AddConstraint("Pose", obj, False) else: shd = pri.addImplicite(obj, "Cube", self.getName(str(name) + "_shd"), obj.Kinematics.Global.Transform, self.options["size"] * .15) self.addToGroup(shd, "deformers") return shd def getNormalFromPos(self, pos): if len(pos) < 3: gear.log( "%s : Not enough references to define normal" % self.fullName, gear.sev_error) return vec.getPlaneNormal(pos[0], pos[1], pos[2]) def getBiNormalFromPos(self, pos): if len(pos) < 3: gear.log( "%s : Not enough references to define binormal" % self.fullName, gear.sev_error) return vec.getPlaneBiNormal(pos[0], pos[1], pos[2]) # ===================================================== def addCtl(self, parent, name, t, color, icon, **kwargs): prim = None if self.getName(name) in self.rig.guide.controlers.keys(): prim = self.rig.guide.controlers[self.getName(name)] #Get color from rig try: rR = prim.obj.Properties('display').Parameters(12).GetValue2( None) rG = prim.obj.Properties('display').Parameters(13).GetValue2( None) rB = prim.obj.Properties('display').Parameters(14).GetValue2( None) color = [rR, rG, rB] except: pass ctl = ico.primOrIcon(prim, parent, self.getName(name), t, color, icon, kwargs=kwargs) self.addToCtlGroup(ctl) return ctl # ===================================================== # PROPERTY # ===================================================== ## Get the host for the properties. # @param self def getHost(self): self.uihost = self.rig.findUIHost(self.settings["uiHost"]) self.anim_prop = self.uihost.anim_prop self.setup_prop = self.uihost.setup_prop ## Add parameters to the anim and setup properties to control the component.\n # REIMPLEMENT. This method should be reimplemented in each component. # @param self def addParameters(self): return ## Define the layout of the anim and setup properties.\n # REIMPLEMENT. This method should be reimplemented in each component. # @param self def addLayout(self): return ## Define the logic of the anim and setup properties.\n # REIMPLEMENT. This method should be reimplemented in each component. # @param self def addLogic(self): return def setUI(self): # Layout for source_layout, target_layout in ((self.anim_layout, self.uihost.anim_layout), (self.setup_layout, self.uihost.setup_layout)): target_layout.beforeCode.extend(source_layout.beforeCode) target_layout.afterCode.extend(source_layout.afterCode) for name, tab in source_layout.tabs.items(): newtab = target_layout.addTab(name) if not newtab.items: row = newtab.addRow() r_group = row.addGroup("Right") c_group = row.addGroup("") l_group = row.addGroup("Left") else: row = newtab.items[0] r_group = row.items[0] c_group = row.items[1] l_group = row.items[2] if self.side == "R": group = r_group elif self.side == "C": group = c_group elif self.side == "L": group = l_group group.items.extend(tab.items) # Logic self.uihost.anim_logic.addGlobalCode(self.anim_logic.getValue()) self.uihost.setup_logic.addGlobalCode(self.setup_logic.getValue()) ## Add a parameter to the animation property.\n # Note that animatable and keyable are True per default. # @param self # @param scriptName String - Parameter scriptname. # @param valueType Integer - siVariantType. # @param value Variant - Default parameter value. # @param minimum Variant - mininum value. # @param maximum Variant - maximum value. # @param sugMinimum Variant - suggested mininum value. # @param sugMaximum Variant - suggested maximum value. # @param animatable Boolean - True to make parameter animatable. # @param readOnly Boolean - True to make parameter readOnly. # @param keyable Boolean - True to make parameter keyable. # @return Parameter - The newly created parameter. def addAnimParam(self, scriptName, valueType, value, minimum=None, maximum=None, sugMinimum=None, sugMaximum=None, animatable=True, readOnly=False, keyable=True): capabilities = 1 * animatable + 2 * readOnly + 4 + 2048 * keyable param = self.anim_prop.AddParameter2(self.getName(scriptName), valueType, value, minimum, maximum, sugMinimum, sugMaximum, c.siClassifUnknown, capabilities, scriptName) return param ## Add a parameter to the setup property.\n # Note that animatable and keyable are false per default. # @param self # @param scriptName String - Parameter scriptname. # @param valueType Integer - siVariantType. # @param value Variant - Default parameter value. # @param minimum Variant - mininum value. # @param maximum Variant - maximum value. # @param sugMinimum Variant - suggested mininum value. # @param sugMaximum Variant - suggested maximum value. # @param animatable Boolean - True to make parameter animatable. # @param readOnly Boolean - True to make parameter readOnly. # @param keyable Boolean - True to make parameter keyable. # @return Parameter - The newly created parameter. def addSetupParam(self, scriptName, valueType, value, minimum=None, maximum=None, sugMinimum=None, sugMaximum=None, animatable=False, readOnly=False, keyable=False): capabilities = 1 * animatable + 2 * readOnly + 4 + 2048 * keyable param = self.setup_prop.AddParameter2(self.getName(scriptName), valueType, value, minimum, maximum, sugMinimum, sugMaximum, c.siClassifUnknown, capabilities, scriptName) return param ## Add a parameter to the setup property.\n # Note that animatable and keyable are false per default. # @param self # @param scriptName String - Parameter scriptname. # @param valueType Integer - siVariantType. # @param value Variant - Default parameter value. # @param minimum Variant - mininum value. # @param maximum Variant - maximum value. # @param sugMinimum Variant - suggested mininum value. # @param sugMaximum Variant - suggested maximum value. # @param animatable Boolean - True to make parameter animatable. # @param readOnly Boolean - True to make parameter readOnly. # @param keyable Boolean - True to make parameter keyable. # @return Parameter - The newly created parameter. def addSetupFCurveParam(self, scriptName, ref_fcv): ref_fcv.scriptName = self.getName(scriptName) param = ref_fcv.create(self.setup_prop) return param # ===================================================== # OPERATORS # ===================================================== ## Apply operators, constraint, expressions to the hierarchy.\n # REIMPLEMENT. This method should be reimplemented in each component.\n # We shouldn't create any new object in this method. # @param self def addOperators(self): return # ===================================================== # CONNECTOR # ===================================================== ## Add more connection definition to the set.\n # REIMPLEMENT. This method should be reimplemented in each component.\n # Only if you need to use an new connection (not the standard). # @param self def addConnection(self): return ## Set the relation beetween object from guide to rig.\n # REIMPLEMENT. This method should be reimplemented in each component. # @param self def setRelation(self): for name in self.guide.objectNames: self.relatives[name] = self.root ## Return the relational object from guide to rig. # @param self # @param local name of the guide object. def getRelation(self, name): if name not in self.relatives.keys(): gear.log( "Can't find reference for object : " + self.fullName + "." + name, gear.sev_error) return False return self.relatives[name] def initConnector(self): parent_name = "none" if self.guide.parentComponent is not None: parent_name = self.guide.parentComponent.getName( self.guide.parentLocalName) self.parent = self.rig.findChild(parent_name) self.parent_comp = self.rig.findComponent(parent_name) ## Connect the component to the rest of the rig using the defined connection. # @param def connect(self): if self.settings["connector"] not in self.connections.keys(): gear.log("Unable to connect object", gear.sev_error) return False self.connections[self.settings["connector"]]() return True ## standard connection definition. This is a simple parenting of the root. # @param self def connect_standard(self): self.parent.AddChild(self.root) ## standard connection definition with ik and upv references. # @param self def connect_standardWithIkRef(self): self.parent.AddChild(self.root) # Set the Ik Reference if self.settings["ikrefarray"]: ref_names = self.settings["ikrefarray"].split(",") if len(ref_names) == 1: ref = self.rig.findChild(ref_names[0]) ref.AddChild(self.ik_cns) else: for i, ref_name in enumerate(ref_names): ref = self.rig.findChild(ref_name) cns = self.ik_cns.Kinematics.AddConstraint( "Pose", ref, True) par.addExpression(cns.Parameters("active"), self.pIkRef.FullName + " == " + str(i)) # Set the Upv Reference if self.settings["upvrefarray"]: ref_names = self.settings["upvrefarray"].split(",") if len(ref_names) == 1: ref = self.rig.findChild(ref_names[0]) ref.AddChild(self.upv_cns) else: for i, ref_name in enumerate(ref_names): ref = self.rig.findChild(ref_name) cns = self.upv_cns.Kinematics.AddConstraint( "Pose", ref, True) par.addExpression(cns.Parameters("active"), self.pUpvRef.FullName + " == " + str(i)) ## Post connection actions. # REIMPLEMENT. This method should be reimplemented in each component.\n # @param self def postConnect(self): return # ===================================================== # FINALIZE # ===================================================== def finalize(self): # Set the layout and logic in the ppg if self.ui is not None: self.ui.fillLayoutAndLogic() # ===================================================== # MISC # ===================================================== ## Return the name for component element # @param self # @param name String - Name. def getName(self, name="", side=None): if side is None: side = self.side name = str(name) if name: return self.name + "_" + side + str(self.index) + "_" + name else: return self.fullName # ===================================================== # PROPERTIES # ===================================================== ## return the fullname of the component # @param self def getFullName(self): return self.guide.fullName ## return the type of the component # @param self def getType(self): return self.guide.type fullName = property(getFullName) type = property(getType)