/// <summary> /// Detects the references based on naming and hierarchy. /// </summary> public static void DetectReferencesByNaming(ref BipedReferences references, Transform root, AutoDetectParams autoDetectParams) { if (references == null) { references = new BipedReferences(); } Transform[] children = root.GetComponentsInChildren <Transform>(); // Find limbs DetectLimb(BipedNaming.BoneType.Arm, BipedNaming.BoneSide.Left, ref references.leftUpperArm, ref references.leftForearm, ref references.leftHand, children); DetectLimb(BipedNaming.BoneType.Arm, BipedNaming.BoneSide.Right, ref references.rightUpperArm, ref references.rightForearm, ref references.rightHand, children); DetectLimb(BipedNaming.BoneType.Leg, BipedNaming.BoneSide.Left, ref references.leftThigh, ref references.leftCalf, ref references.leftFoot, children); DetectLimb(BipedNaming.BoneType.Leg, BipedNaming.BoneSide.Right, ref references.rightThigh, ref references.rightCalf, ref references.rightFoot, children); // Find head bone references.head = BipedNaming.GetBone(children, BipedNaming.BoneType.Head); // Find Pelvis references.pelvis = BipedNaming.GetNamingMatch(children, BipedNaming.pelvis); // If pelvis is not an ancestor of a leg, it is not a valid pelvis if (references.pelvis == null || !Hierarchy.IsAncestor(references.leftThigh, references.pelvis)) { if (references.leftThigh != null) { references.pelvis = references.leftThigh.parent; } } // Find spine and head bones if (references.leftUpperArm != null && references.rightUpperArm != null && references.pelvis != null && references.leftThigh != null) { Transform neck = Hierarchy.GetFirstCommonAncestor(references.leftUpperArm, references.rightUpperArm); if (neck != null) { Transform[] inverseSpine = new Transform[1] { neck }; Hierarchy.AddAncestors(inverseSpine[0], references.pelvis, ref inverseSpine); references.spine = new Transform[0]; for (int i = inverseSpine.Length - 1; i > -1; i--) { if (AddBoneToSpine(inverseSpine[i], ref references, autoDetectParams)) { Array.Resize(ref references.spine, references.spine.Length + 1); references.spine[references.spine.Length - 1] = inverseSpine[i]; } } // Head if (references.head == null) { for (int i = 0; i < neck.childCount; i++) { Transform child = neck.GetChild(i); if (!Hierarchy.ContainsChild(child, references.leftUpperArm) && !Hierarchy.ContainsChild(child, references.rightUpperArm)) { references.head = child; break; } } } } } // Find eye bones Transform[] eyes = BipedNaming.GetBonesOfType(BipedNaming.BoneType.Eye, children); references.eyes = new Transform[0]; if (autoDetectParams.includeEyes) { for (int i = 0; i < eyes.Length; i++) { if (AddBoneToEyes(eyes[i], ref references, autoDetectParams)) { Array.Resize(ref references.eyes, references.eyes.Length + 1); references.eyes[references.eyes.Length - 1] = eyes[i]; } } } }
private static bool IsNeckBone(Transform bone, Transform leftUpperArm) { return((!(leftUpperArm.parent != null) || !(leftUpperArm.parent == bone)) && !Hierarchy.IsAncestor(leftUpperArm, bone)); }
private static bool AddBoneToEyes(Transform bone, ref BipedReferences references, BipedReferences.AutoDetectParams autoDetectParams) { return((!(references.head != null) || Hierarchy.IsAncestor(bone, references.head)) && !(bone.GetComponent <SkinnedMeshRenderer>() != null)); }
public static void DetectReferencesByNaming(ref BipedReferences references, Transform root, BipedReferences.AutoDetectParams autoDetectParams) { if (references == null) { references = new BipedReferences(); } Transform[] componentsInChildren = root.GetComponentsInChildren <Transform>(); BipedReferences.DetectLimb(BipedNaming.BoneType.Arm, BipedNaming.BoneSide.Left, ref references.leftUpperArm, ref references.leftForearm, ref references.leftHand, componentsInChildren); BipedReferences.DetectLimb(BipedNaming.BoneType.Arm, BipedNaming.BoneSide.Right, ref references.rightUpperArm, ref references.rightForearm, ref references.rightHand, componentsInChildren); BipedReferences.DetectLimb(BipedNaming.BoneType.Leg, BipedNaming.BoneSide.Left, ref references.leftThigh, ref references.leftCalf, ref references.leftFoot, componentsInChildren); BipedReferences.DetectLimb(BipedNaming.BoneType.Leg, BipedNaming.BoneSide.Right, ref references.rightThigh, ref references.rightCalf, ref references.rightFoot, componentsInChildren); references.head = BipedNaming.GetBone(componentsInChildren, BipedNaming.BoneType.Head, BipedNaming.BoneSide.Center, Array.Empty <string[]>()); references.pelvis = BipedNaming.GetNamingMatch(componentsInChildren, new string[][] { BipedNaming.pelvis }); if ((references.pelvis == null || !Hierarchy.IsAncestor(references.leftThigh, references.pelvis)) && references.leftThigh != null) { references.pelvis = references.leftThigh.parent; } if (references.leftUpperArm != null && references.rightUpperArm != null && references.pelvis != null && references.leftThigh != null) { Transform firstCommonAncestor = Hierarchy.GetFirstCommonAncestor(references.leftUpperArm, references.rightUpperArm); if (firstCommonAncestor != null) { Transform[] array = new Transform[] { firstCommonAncestor }; Hierarchy.AddAncestors(array[0], references.pelvis, ref array); references.spine = new Transform[0]; for (int i = array.Length - 1; i > -1; i--) { if (BipedReferences.AddBoneToSpine(array[i], ref references, autoDetectParams)) { Array.Resize <Transform>(ref references.spine, references.spine.Length + 1); references.spine[references.spine.Length - 1] = array[i]; } } if (references.head == null) { for (int j = 0; j < firstCommonAncestor.childCount; j++) { Transform child = firstCommonAncestor.GetChild(j); if (!Hierarchy.ContainsChild(child, references.leftUpperArm) && !Hierarchy.ContainsChild(child, references.rightUpperArm)) { references.head = child; break; } } } } } Transform[] bonesOfType = BipedNaming.GetBonesOfType(BipedNaming.BoneType.Eye, componentsInChildren); references.eyes = new Transform[0]; if (autoDetectParams.includeEyes) { for (int k = 0; k < bonesOfType.Length; k++) { if (BipedReferences.AddBoneToEyes(bonesOfType[k], ref references, autoDetectParams)) { Array.Resize <Transform>(ref references.eyes, references.eyes.Length + 1); references.eyes[references.eyes.Length - 1] = bonesOfType[k]; } } } }
/* * Check if the limb is properly set up * */ private static bool CheckLimb(Transform bone1, Transform bone2, Transform bone3, bool log) { if (bone2.position == bone1.position) { if (log) { Warning.Log("Second bone's position equals first bone's position in the biped's limb.", bone2, true); } return(false); } if (bone3.position == bone2.position) { if (log) { Warning.Log("Third bone's position equals second bone's position in the biped's limb.", bone3, true); } return(false); } Transform duplicate = (Transform)Hierarchy.ContainsDuplicate(new Transform[3] { bone1, bone2, bone3 }); if (duplicate != null) { if (log) { Warning.Log(duplicate.name + " is represented multiple times in the same BipedReferences limb.", bone1, true); } return(false); } if (!Hierarchy.HierarchyIsValid(new Transform[3] { bone1, bone2, bone3 })) { if (log) { Warning.Log( "BipedReferences limb hierarchy is invalid. Bone transforms in a limb do not belong to the same ancestry. Please make sure the bones are parented to each other. " + "Bones: " + bone1.name + ", " + bone2.name + ", " + bone3.name, bone1, true); } return(false); } Vector3 cross = Vector3.Cross(bone2.position - bone1.position, bone3.position - bone1.position); if (cross == Vector3.zero) { if (log) { Warning.Log( "BipedReferences limb is completely stretched out in the initial pose. IK solver can not calculate the default bend plane for the limb. " + "Please make sure you character's limbs are at least slightly bent in the initial pose. " + "First bone: " + bone1.name + ", second bone: " + bone2.name + ".", bone1, true); } return(false); } return(true); }
// Check if spine is properly set up private static bool CheckSpineError(BipedReferences references, bool log) { if (references.spine.Length == 0) { return(true); } for (int i = 0; i < references.spine.Length; i++) { if (references.spine[i] == null) { if (log) { Warning.Log("BipedReferences spine bone at index " + i + " is null.", references.root, true); } return(false); } } Transform duplicate = (Transform)Hierarchy.ContainsDuplicate(references.spine); if (duplicate != null) { if (log) { Warning.Log(duplicate.name + " is represented multiple times in BipedReferences spine.", references.spine[0], true); } return(false); } if (!Hierarchy.HierarchyIsValid(references.spine)) { if (log) { Warning.Log("BipedReferences spine hierarchy is invalid. Bone transforms in the spine do not belong to the same ancestry. Please make sure the bones are parented to each other.", references.spine[0], true); } return(false); } for (int i = 0; i < references.spine.Length; i++) { bool matchesParentPosition = false; if (i == 0 && references.spine[i].position == references.pelvis.position) { matchesParentPosition = true; } if (i != 0 && references.spine.Length > 1 && references.spine[i].position == references.spine[i - 1].position) { matchesParentPosition = true; } if (matchesParentPosition) { if (log) { Warning.Log("Biped's spine bone nr " + i + " position is the same as it's parent spine/pelvis bone's position. Please remove this bone from the spine.", references.spine[i], true); } return(false); } } return(true); }
// Check if the limb is properly set up private static bool CheckLimbError(Transform bone1, Transform bone2, Transform bone3, bool log) { if (bone1 == null) { if (log) { Warning.Log("Bone 1 of a BipedReferences limb is null.", bone2, true); } return(false); } if (bone2 == null) { if (log) { Warning.Log("Bone 2 of a BipedReferences limb is null.", bone3, true); } return(false); } if (bone3 == null) { if (log) { Warning.Log("Bone 3 of a BipedReferences limb is null.", bone1, true); } return(false); } if (bone2.position == bone1.position) { if (log) { Warning.Log("Second bone's position equals first bone's position in the biped's limb.", bone2, true); } return(false); } if (bone3.position == bone2.position) { if (log) { Warning.Log("Third bone's position equals second bone's position in the biped's limb.", bone3, true); } return(false); } Transform duplicate = (Transform)Hierarchy.ContainsDuplicate(new Transform[3] { bone1, bone2, bone3 }); if (duplicate != null) { if (log) { Warning.Log(duplicate.name + " is represented multiple times in the same BipedReferences limb.", bone1, true); } return(false); } if (!Hierarchy.HierarchyIsValid(new Transform[3] { bone1, bone2, bone3 })) { if (log) { Warning.Log( "BipedReferences limb hierarchy is invalid. Bone transforms in a limb do not belong to the same ancestry. Please make sure the bones are parented to each other. " + "Bones: " + bone1.name + ", " + bone2.name + ", " + bone3.name, bone1, true); } return(false); } return(true); }
public static bool IsAncestor(Transform transform, Transform ancestor) { return(transform == null || ancestor == null || (!(transform.parent == null) && (transform.parent == ancestor || Hierarchy.IsAncestor(transform.parent, ancestor)))); }