def BuildFKRig(parent, crv, ppg, side=MIDDLE, simple=False): prefix = 'M_' if side == LEFT: prefix = 'L_' elif side == RIGHT: prefix = 'R_' r = ppg.Parameters('{}ColorR_FK'.format(prefix)).Value g = ppg.Parameters('{}ColorG_FK'.format(prefix)).Value b = ppg.Parameters('{}ColorB_FK'.format(prefix)).Value model = parent.Model builder = model.Properties('RigBuilder') if not builder: XSI.LogMessage('[RigControl] Invalid parent object, aborted !') return False elem_ppg = crv.Properties('RigElement') if not elem_ppg: XSI.LogMessage( '[RigControl] Guide curve is not a rig element, aborted !') return False ctrls = XSIFactory.CreateActiveXObject('XSI.Collection') basename = crv.Name.replace('_Crv', '') vertices = crv.ActivePrimitive.Geometry.Points up_x = elem_ppg.Parameters('UpVectorX').Value up_y = elem_ppg.Parameters('UpVectorY').Value up_z = elem_ppg.Parameters('UpVectorZ').Value up_vector = XSIMath.CreateVector3(up_x, up_y, up_z) direction = XSIMath.CreateVector3() for idx, vertex in enumerate(vertices): transform = XSIMath.CreateTransform() p0 = vertex.Position transform.SetTranslation(p0) if idx < vertices.Count - 1: p1 = vertices[idx + 1].Position direction.Sub(p1, p0) direction.NormalizeInPlace() rot = Utils.GetRotationFromTwoVectors(direction, up_vector) transform.SetRotation(rot) fk = Icon.simple(parent, '{}_FK{}_Ctrl'.format(basename, idx + 1), [r, g, b], transform, p1) else: fk = Icon.simple(parent, '{}_FK{}_Ctrl'.format(basename, idx + 1), [r, g, b], transform, p0) parent = fk ctrls.Add(fk) Utils.ResetStaticKinematicState(ctrls) XSI.SetNeutralPose(ctrls, 'siSRT', '') Utils.GroupSetup(model, ctrls, inGroupName='FK_Rig') return True
def ProjectOnPlane(inPoint, inPlaneNormal): vProjection = XSIMath.CreateVector3() pProjection = XSIMath.CreateVector3() dot = inPoint.Dot(inPlaneNormal) scaleChange = (dot / math.pow(inPlaneNormal.Length(), 2)) vProjection.Scale(scaleChange, inPlaneNormal) pProjection.Sub(inPoint, vProjection) return pProjection
def GetOrientationFromPickPosition(pos): if isinstance(pos, list) and len(pos) > 1: rot = [] vm = XSI.Desktop.ActiveLayout.Views("vm") focus = vm.GetAttributeValue("focusedviewport") if focus: cam = vm.GetAttributeValue("activecamera:" + focus) else: cam = "Right" y = XSIMath.CreateVector3(0, 1, 0) if cam == "Right": y.Set(1, 0, 0) elif cam == "Top": y.Set(0, 1, 0) elif cam == "Front": y.Set(0, 0, 1) else: x1 = XSIMath.CreateVector3() x2 = XSIMath.CreateVector3() x1.Sub(pos[1], pos[0]) x2.Sub(pos[len(pos) - 1], pos[len(pos) - 2]) y.Cross(x1, x2) y.NormalizeInPlace() for idx in range(len(pos) - 1): start = pos[idx] end = pos[idx + 1] delta = XSIMath.CreateVector3() delta.Sub(end, start) ''' n = AddNull(xsi.ActiveSceneRoot,4,1,"Start") t = n.Kinematics.Global.Transform t.SetTranslation(start) n.Kinematics.Global.Transform = t n = AddNull(xsi.ActiveSceneRoot,4,1,"End") t = n.Kinematics.Global.Transform t.SetTranslation(end) n.Kinematics.Global.Transform = t ''' r = GetRotationFromTwoVectors(delta, y) rot.append(r) # duplicate the last array item rot.append(rot[len(rot) - 1]) return rot else: return XSIMath.CreateRotation()
def MatchRotation(Obj, Target): T = Target.Kinematics.Global.Transform O = Obj.Kinematics.Global.Transform R = XSIMath.CreateRotation() T.GetRotation(R) O.SetRotation(R) Obj.Kinematics.Global.Transform = O
def BuildCurveOnPositions(inPositions, inDegree=0, inClose=0, inOffset=XSIMath.CreateVector3()): if len(inPositions) < 2: XSI.LogMessage( "BuildCurveOnPosition aborted :: Not enough input positions!!", constants.siError) return if len(inPositions) < 4: inDegree = 0 aPos = [] for p in inPositions: aPos.append(p.X + inOffset.X) aPos.append(p.Y + inOffset.Y) aPos.append(p.Z + inOffset.Z) aPos.append(1) if inDegree == 0: outCrv = XSI.ActiveSceneRoot.AddNurbsCurve(aPos, None, inClose, 1) else: outCrv = XSI.ActiveSceneRoot.AddNurbsCurve(aPos, None, inClose, 3) return outCrv
def GetAveragePosition(positions): x = XSIMath.CreateVector3() for p in positions: x.AddInPlace(p) x.ScaleInPlace(1.0 / len(positions)) return x
def GetRotationFromTwoVectors(direction, up=XSIMath.CreateVector3(0, 1, 0)): cross = XSIMath.CreateVector3() side = XSIMath.CreateVector3() direction.NormalizeInPlace() up.NormalizeInPlace() cross.Cross(direction, up) cross.NormalizeInPlace() side.Cross(cross, direction) side.NormalizeInPlace() m = XSIMath.CreateMatrix3() m.Set(cross.X, cross.Y, cross.Z, direction.X, direction.Y, direction.Z, side.X, side.Y, side.Z) r = XSIMath.CreateRotation() r.SetFromMatrix3(m) return r
def DistanceBetweenTwoObjects(start, end): if not start or not end: XSI.LogMessage("[Distance between two objects] Invalid Inputs!!", constants.siWarning) sT = start.Kinematics.Global.Transform eT = end.Kinematics.Global.Transform delta = XSIMath.CreateVector3() delta.Sub(eT.Translation, sT.Translation) return delta.Length()
def GetPositions(objects): outPos = [] for o in objects: t = o.Kinematics.Global.Transform p = XSIMath.CreateVector3() t.GetTranslation(p) outPos.append(p) return outPos
def FindClosestIndex(pnt, positions, indices): """ Find closest index :param Vector3 pnt: SDK Vector3 object :param Vector3Array positions: SDK PointPositionArray :param list indices: indices list :return int: closest vertex index """ delta = XSIMath.CreateVector3() closest_distance = sys.float_info.max closest_idx = 0 for idx, p2 in enumerate(positions): t = XSIMath.CreateVector3(pnt.X, pnt.Y, pnt.Z) delta.Sub(t, p2) distance = delta.Length() if distance < closest_distance: closest_distance = distance closest_idx = idx return indices[closest_idx]
def PickPosition(inMessage="Pick Position"): if not inMessage: inMessage = "Pick Position" picked = XSI.PickPosition(inMessage, inMessage, None, None, None, None) button = picked("ButtonPressed") if button: x = picked("PosX") y = picked("PosY") z = picked("PosZ") outVec = XSIMath.CreateVector3(x, y, z) return outVec else: return None
def BuildCurveOnSymmetrizedPositions(inPositions, inAxis=0, inDegree=0, inClose=0): if len(inPositions) < 1: XSI.LogMessage( "BuildCurveOnSymmetrizedPosition aborted :: Not enough input positions!!", constants.siError) return axis = XSIMath.CreateVector3(-1, 1, 1) if inAxis == 1: axis.Set(1, -1, 1) elif inAxis == 2: axis.Set(1, 1, -1) newPos = [] last = len(inPositions) - 1 for i in range(len(inPositions)): p = inPositions[last - i] newPos.append(p.X * axis.X) newPos.append(p.Y * axis.Y) newPos.append(p.Z * axis.Z) newPos.append(1) # middle pos newPos.append(0) newPos.append(inPositions[0].Y) newPos.append(inPositions[0].Z) newPos.append(1) for p in inPositions: newPos.append(p.X) newPos.append(p.Y) newPos.append(p.Z) newPos.append(1) if inDegree == 0: outCrv = XSI.ActiveSceneRoot.AddNurbsCurve(newPos, None, inClose, 1) else: outCrv = XSI.ActiveSceneRoot.AddNurbsCurve(newPos, None, inClose, 3) return outCrv
def CreateGuide(self): builder = self.GetBuilder() if self.CheckElementExist(): XSI.LogMessage('[CreateControlElement] : ' + self.fullname + '_Ctrl already exist ---> aborted...!') return False t = XSIMath.CreateTransform() t.SetTranslation(self.position) self.crv = RIG_CONTROL_ICON[builder.Parameters( "ControlIconType").Value] self.GetControlColor() color = [self.colorrik, self.colorgik, self.colorbik] self.size = builder.Parameters("GlobalSize").Value self.crv = Icon.IRIcon(self.parent, self.fullname + "_Ctrl", t, color, self.icon, self.size, self.size, self.size) Utils.GroupSetup(self.model, [self.crv], "Control_Curves") return True
def Symmetrize(self): if self.side == MIDDLE: XSI.LogMessage( "[CreateControlElement] : Can't symmetrize middle elements ---> aborted...!" ) return None axis = self.builder.Parameters("SymmetryAxis").Value self.symparent = self.model.FindChild( self.ctrl.Parent.Name.replace(self.prefix, self.symprefix)) if not self.symparent: self.symparent = self.ctrl.Parent color = [self.colorrik, self.colorgik, self.colorbik] self.symctrl = Icon.IRIcon(self.symparent, self.symfullname + "_Ctrl", XSIMath.CreateTransform(), color, self.icon, self.size, self.size, self.size) Utils.SimpleSymmetry(self.symctrl, self.ctrl, axis) '''
def BuildCurveOnObjectsPosition(inObjects, inDegree=0, inClose=0, inConstraint=1, inOffset=XSIMath.CreateVector3()): if len(inObjects) < 2: XSI.LogMessage( "BuildCurveOnPoints aborted :: Not enough input objects!!", constants.siError) return if len(inObjects) < 4: inDegree = 0 pPos = GetPositions(inObjects) aPos = [] for p in pPos: aPos.append(p.X + inOffset.X) aPos.append(p.Y + inOffset.Y) aPos.append(p.Z + inOffset.Z) aPos.append(1) if inDegree == 0: outCrv = XSI.ActiveSceneRoot.AddNurbsCurve(aPos, None, inClose, 1) else: outCrv = XSI.ActiveSceneRoot.AddNurbsCurve(aPos, None, inClose, 3) if inConstraint == 1: crvGeom = outCrv.ActivePrimitive.Geometry for p in crvGeom.Points: oCluster = crvGeom.AddCluster(constants.siVertexCluster, "Pnt" + str(p.Index + 1), p.Index) XSI.ApplyOp("ClusterCenter", str(oCluster) + ";" + str(inObjects[p.Index]), 0, 0, None, 2) return outCrv
def BuildSRTRig(parent, crv, ppg, side=MIDDLE, simple=False): prefix = 'M_' if side == LEFT: prefix = 'L_' elif side == RIGHT: prefix = 'R_' r = ppg.Parameters('{}ColorR_FK'.format(prefix)).Value g = ppg.Parameters('{}ColorG_FK'.format(prefix)).Value b = ppg.Parameters('{}ColorB_FK'.format(prefix)).Value model = parent.Model builder = model.Properties('RigBuilder') if not builder: XSI.LogMessage('[RigControl] : Invalid Parent Object ---> Aborted!') return False elem_ppg = crv.Properties('RigElement') if not elem_ppg: XSI.LogMessage( '[RigControl] : Guide Curve is NOT a Rig Element ---> Aborted!') return False controls = XSIFactory.CreateActiveXObject('XSI.Collection') basename = crv.Name.replace('_Crv', '') vertices = crv.ActivePrimitive.Geometry.Points for idx, vertex in enumerate(vertices): transform = XSIMath.CreateTransform() p0 = vertex.Position transform.SetTranslation(p0) srt = Icon.IRIcon(parent, '{}{}_Ctrl'.format(basename, idx), transform, [r, g, b], 'sphere', 0.1, 0.1, 0.1) controls.Add(srt) Utils.ResetStaticKinematicState(controls) XSI.SetNeutralPose(controls, 'siSRT', '') Utils.GroupSetup(model, controls, inGroupName='FK_Rig')
def PickPositionInVolume(inMessage="Pick Position"): # enable snap option XSI.SetValue("preferences.SnapProperties.Enable2D", True, None) XSI.SetValue("preferences.SnapProperties.Enable", True, None) if not inMessage: inMessage = "Pick Position" picked = XSI.PickPosition(inMessage, inMessage, None, None, None, None) button = picked("ButtonPressed") if button: x = picked("PosX") y = picked("PosY") z = picked("PosZ") else: return None outVec = XSIMath.CreateVector3(x, y, z) # disable snap option XSI.SetValue("preferences.SnapProperties.Enable2D", False, None) XSI.SetValue("preferences.SnapProperties.Enable", False, None) return outVec
def BuildIK2BonesRig(parent, crv, ppg): name = crv.Name.replace("_Crv", "") side = MIDDLE if name.find("L_", 0, 2) > -1: side = LEFT elif name.find("R_", 0, 2) > -1: side = RIGHT prefix = "M_" if side == LEFT: prefix = "L_" elif side == RIGHT: prefix = "R_" ppg.Parameters("GlobalSize").Value r = ppg.Parameters(prefix + "ColorR_IK").Value g = ppg.Parameters(prefix + "ColorG_IK").Value b = ppg.Parameters(prefix + "ColorB_IK").Value pnts = crv.ActivePrimitive.Geometry.Points if pnts.Count == 3: p0 = pnts[0].Position p1 = pnts[1].Position p2 = pnts[2].Position else: last = pnts.Count - 1 p0 = pnts[0].Position pos = [] for i in range(1, last): pos.append(pnts[i].Position) p1 = Utils.GetAveragePosition(pos) p2 = pnts[last].Position dir1 = XSIMath.CreateVector3() dir1.Sub(p0, p1) dir2 = XSIMath.CreateVector3() dir2.Sub(p1, p2) length = dir1.Length() + dir2.Length() plane = XSIMath.CreateVector3() plane.Cross(dir1, dir2) plane.NormalizeInPlace() offset = XSIMath.CreateVector3() offset.Normalize(dir1) offset.ScaleInPlace(-length * 0.5) offset.AddInPlace(p1) l1 = dir1.Length() l2 = dir2.Length() transform = XSIMath.CreateTransform() transform.SetTranslation(p0) root = Icon.IRIcon(parent, name + "_Root_Ctrl", transform, [r, g, b], "cube", 0.1 * length, 0.1 * length, 0.1 * length) ik = Utils.MakeRigNull(parent, 1, name + "_IK") transform.SetTranslation(p1) ik.Kinematics.Global.Transform = transform tree = ICETree.CreateICETree(ik, "IK", 2) ik_node = XSI.AddICECompoundNode("IK2BonesKinematics", tree) XSI.ConnectICENodes(str(tree) + ".port1", str(ik_node) + ".Execute") # set ik values XSI.SetValue( str(ik_node) + ".Reference", "this_model." + name + "_Root_Ctrl", "") XSI.SetValue( str(ik_node) + ".Reference1", "this_model." + name + "_Eff_Ctrl", "") XSI.SetValue( str(ik_node) + ".Reference2", "this_model." + name + "_UpV_Ctrl", "") XSI.SetValue(str(ik_node) + ".LengthA", l1, "") XSI.SetValue(str(ik_node) + ".LengthB", l2, "") knee = Icon.IRIcon(ik, name + "_Knee_Ctrl", transform, [r, g, b], "sphere", 0.1 * length, 0.1 * length, 0.1 * length) transform.SetTranslation(offset) upv = Icon.IRIcon(root, name + "_UpV_Ctrl", transform, [r, g, b], "pyramid", 0.05 * length, 0.05 * length, 0.05 * length) transform.SetTranslation(p2) eff = Icon.IRIcon(parent, name + "_Eff_Ctrl", transform, [r, g, b], "square", length, length, length) Utils.ResetStaticKinematicState([root, knee, eff]) Utils.GroupSetup(parent.Model, [root, knee, eff], "IK_Rig") XSI.SetNeutralPose([root, knee, eff, upv], "siSRT", "")
def BuildFootRollRig(parent, crv, ppg, side=MIDDLE, simple=False): prefix = 'M_' if side == LEFT: prefix = 'L_' elif side == RIGHT: prefix = 'R_' basename = crv.Name.replace("_Crv", "") r = ppg.Parameters('{}ColorR_FK'.format(prefix)).Value g = ppg.Parameters('{}ColorG_FK'.format(prefix)).Value b = ppg.Parameters('{}ColorB_FK'.format(prefix)).Value axis = XSIMath.CreateVector3() d1 = XSIMath.CreateVector3() d2 = XSIMath.CreateVector3() points = crv.ActivePrimitive.Geometry.Points pos = [] for point in points: pos.append(point.Position) last = points.Count - 1 d1.Sub(pos[1], pos[0]) d2.Sub(pos[last], pos[0]) d1.NormalizeInPlace() d2.NormalizeInPlace() axis.Cross(d1, d2) # build root control min_z = pos[0].Z for i, point in enumerate(pos): if i == 0: continue if point.Z < min_z: min_z = point.Z average = Utils.GetAveragePosition(pos) average.Z = min_z length = Utils.GetCurveLength(crv) transform = XSIMath.CreateTransform() transform.SetTranslation(average) main = Icon.IRIcon(parent, '{}_MainControl'.format(basename), transform, [r, g, b], 'circle', 0.5 * length, 0.5 * length, 0.5 * length) parent = main parents = [] ctrls = [] # build reverse structure for i in range(0, last): transform.SetTranslation(pos[last - i]) parent = Icon.IRIcon(parent, '{}{}{}_Ctrl'.format(prefix, basename, i), transform, [r, g, b], 'bendedarrow2', 0.2 * length, 0.2 * length, 0.2 * length) parents.append(parent) ctrls.append(parent) # build final control structure fks = [] for i in range(0, last + 1): transform.SetTranslation(pos[last - i]) if i == 0: icon = Icon.IRIcon(main, '{}{}{}_Ctrl'.format(prefix, basename, i), transform, [r, g, b], "sphere", 0.1 * length, 0.1 * length, 0.1 * length) fks.append(icon) ctrls.append(icon) else: icon = Icon.IRIcon(parents[i - 1], '{}{}{}_Ctrl'.format(prefix, basename, i), transform, [r, g, b], 'sphere', 0.1 * length, 0.1 * length, 0.1 * length) fks.append(icon) ctrls.append(icon) Utils.ResetStaticKinematicState(fks) Utils.GroupSetup(parent.Model, fks, 'IK_Rig') XSI.SetNeutralPose(ctrls, 'siSRT', '') Utils.GroupSetup(parent.Model, ctrls, 'Anim_Controls')
def CreateEnvelopeNullsFromSkeletonCloud(model): cloud = model.FindChild('ICE_Skeleton') grp = Utils.GroupSetup(model, None, 'Envelope') root = model.FindChild('Envelopes', constants.siNullPrimType) if root: XSI.SelectObj(root, 'BRANCH') XSI.DeleteObj() root = model.AddNull('Envelopes') idx = 0 attrs = cloud.ActivePrimitive.ICEAttributes pos = attrs('PointPosition').DataArray scl = attrs('Scale').DataArray ori = attrs('Orientation').DataArray # we have to display this attribute for accessing it emit = cloud.ActivePrimitive.ICETrees(1) node = emit.Nodes(0) XSI.LogMessage(node) XSI.SetValue('{}.Show_Name'.format(node), True, '') skeleton_name = cloud.ActivePrimitive.GetICEAttributeFromName( 'SkeletonName').DataArray XSI.SetValue('{}.Show_Name'.format(node), False, '') group = Utils.GroupSetup(model, None, 'Envelope') t = XSIMath.CreateTransform() last_name = '' sub_index = 1 for idx in xrange(cloud.ActivePrimitive.Geometry.Points.Count): p = pos[idx] o = ori[idx] s = scl[idx] t.SetTranslation(p) t.SetRotation(o) t.SetScaling(s) ''' n = root.AddNull("Buffer"+str(id)) tr = tree.CreateICETree(n,"Kinematics") node = xsi.AddICECompoundNode("BindTransformToPoint", str(tr)) xsi.ConnectICENodes(str(tr)+".port1", str(node)+".Execute") xsi.SetValue(str(node)+".ID", id, "") ''' current_name = skeleton_name[idx] if not skeleton_name: XSI.LogMessage('You need to display SkeletonName ICE Attribute !', constants.siWarning) break else: if not current_name == last_name: last_name = current_name sub_index = 1 n = root.AddNull('{}{}_Env'.format(current_name, sub_index)) n.ActivePrimitive.Primary_Icon = 4 group.AddMember(n) n.Kinematics.Global.Transform = t idx += 1 sub_index += 1 return grp