static Arm GetArm(Node shoulder) { var bones = shoulder.Traverse().ToArray(); switch (bones.Length) { case 0: case 1: case 2: throw new NotImplementedException(); case 3: return(new Arm { UpperArm = bones[0], LowerArm = bones[1], Hand = bones[2], }); default: return(new Arm { Shoulder = bones[0], UpperArm = bones[1], LowerArm = bones[2], Hand = bones[3], }); } }
static public Dictionary <HumanoidBones, Node> DetectByName(Node root, Dictionary <string, HumanoidBones> map) { var dictionary = new Dictionary <HumanoidBones, Node>(); foreach (var bone in root.Traverse()) { if (map.TryGetValue(bone.Name, out HumanoidBones humanbone)) { if (humanbone != HumanoidBones.unknown) { dictionary.Add(humanbone, bone); } } else if (Enum.TryParse <HumanoidBones>(bone.Name, true, out HumanoidBones result)) { humanbone = (HumanoidBones)result; dictionary.Add(humanbone, bone); } else { // throw new NotImplementedException(); } } return(dictionary); }
static Leg GetLeg(Node leg) { var bones = leg.Traverse().Where(x => string.IsNullOrEmpty(x.Name) || !x.Name.ToLower().Contains("buttock")).ToArray(); switch (bones.Length) { case 0: case 1: case 2: throw new NotImplementedException(); case 3: return(new Leg { UpperLeg = bones[0], LowerLeg = bones[1], Foot = bones[2], }); default: return(new Leg { UpperLeg = bones[bones.Length - 4], LowerLeg = bones[bones.Length - 3], Foot = bones[bones.Length - 2], Toes = bones[bones.Length - 1], }); } }
static ValueTuple <Node, Node> GetUpperLower(Node root) { var legL = root.Traverse().FirstOrDefault(x => x.HumanoidBone == HumanoidBones.leftUpperLeg); var legR = root.Traverse().FirstOrDefault(x => x.HumanoidBone == HumanoidBones.rightUpperLeg); var head = root.Traverse().FirstOrDefault(x => x.HumanoidBone == HumanoidBones.head); var parentL = legL.Parent; var parentR = legR.Parent; if (parentL != parentR) { throw new Exception("different leftLeg parent and rightLeg parent"); } var lower = parentL; var upperAncestors = head.Ancestors().ToList(); if (upperAncestors.Any(x => x == lower)) { throw new Exception("lower is ancestor of head"); } var lowerAncestors = legL.Ancestors().ToList(); while (true) { if (upperAncestors.Last() != lowerAncestors.Last()) { break; } upperAncestors.RemoveAt(upperAncestors.Count - 1); lowerAncestors.RemoveAt(lowerAncestors.Count - 1); } return(upperAncestors.Last(), lowerAncestors.Last()); }
public Dictionary <HumanoidBones, Node> GetBoneMap() { return(Root.Traverse() .Where(x => x.HumanoidBone.HasValue) .ToDictionary(x => x.HumanoidBone.Value, x => x)); }
static public Dictionary <HumanoidBones, Node> DetectByPosition(Node root) { var hips = root.Traverse().First(x => { // 3分岐以上で // // 子孫が以下の構成持ちうるもの // // spine, head, (upper, lower, hand) x 2 // (upper, lower, foot) // (upper, lower, foot) return(x.Children.Where(y => y.Traverse().Count() >= 3).Count() >= 3); }); Node spine, hip_L, hip_R; GetSpineAndHips(hips, out spine, out hip_L, out hip_R); if (hip_L.Equals(hip_R)) { throw new Exception(); } var legLeft = GetLeg(hip_L); var legRight = GetLeg(hip_R); var spineToChest = new List <Node>(); foreach (var x in spine.Traverse()) { spineToChest.Add(x); if (x.Children.Count == 3) { break; } } Func <Vector3, Vector3, bool> isLeft = default(Func <Vector3, Vector3, bool>); if (legLeft.UpperLeg.SkeletonLocalPosition.Z == legRight.UpperLeg.SkeletonLocalPosition.Z) { isLeft = (l, r) => l.X < r.X; } else { isLeft = (l, r) => l.Z < r.Z; } Node neck, shoulder_L, shoulder_R; GetNeckAndArms(spineToChest.Last(), out neck, out shoulder_L, out shoulder_R, isLeft); var armLeft = GetArm(shoulder_L); var armRight = GetArm(shoulder_R); var neckToHead = neck.Traverse().ToArray(); // // set result // var skeleton = new Dictionary <HumanoidBones, Node>(); Action <HumanoidBones, Node> AddBoneToSkeleton = (b, t) => { if (t != null) { t.HumanoidBone = b; skeleton[b] = t; } }; AddBoneToSkeleton(HumanoidBones.hips, hips); switch (spineToChest.Count) { case 0: throw new Exception(); case 1: AddBoneToSkeleton(HumanoidBones.spine, spineToChest[0]); break; case 2: AddBoneToSkeleton(HumanoidBones.spine, spineToChest[0]); AddBoneToSkeleton(HumanoidBones.chest, spineToChest[1]); break; case 3: AddBoneToSkeleton(HumanoidBones.spine, spineToChest[0]); AddBoneToSkeleton(HumanoidBones.chest, spineToChest[1]); AddBoneToSkeleton(HumanoidBones.upperChest, spineToChest[2]); break; default: AddBoneToSkeleton(HumanoidBones.spine, spineToChest[0]); AddBoneToSkeleton(HumanoidBones.chest, spineToChest[1]); AddBoneToSkeleton(HumanoidBones.upperChest, spineToChest.Last()); break; } switch (neckToHead.Length) { case 0: throw new Exception(); case 1: AddBoneToSkeleton(HumanoidBones.head, neckToHead[0]); break; case 2: AddBoneToSkeleton(HumanoidBones.neck, neckToHead[0]); AddBoneToSkeleton(HumanoidBones.head, neckToHead[1]); break; default: AddBoneToSkeleton(HumanoidBones.neck, neckToHead[0]); AddBoneToSkeleton(HumanoidBones.head, neckToHead.Where(x => x.Parent.Children.Count == 1).Last()); break; } AddBoneToSkeleton(HumanoidBones.leftUpperLeg, legLeft.UpperLeg); AddBoneToSkeleton(HumanoidBones.leftLowerLeg, legLeft.LowerLeg); AddBoneToSkeleton(HumanoidBones.leftFoot, legLeft.Foot); AddBoneToSkeleton(HumanoidBones.leftToes, legLeft.Toes); AddBoneToSkeleton(HumanoidBones.rightUpperLeg, legRight.UpperLeg); AddBoneToSkeleton(HumanoidBones.rightLowerLeg, legRight.LowerLeg); AddBoneToSkeleton(HumanoidBones.rightFoot, legRight.Foot); AddBoneToSkeleton(HumanoidBones.rightToes, legRight.Toes); AddBoneToSkeleton(HumanoidBones.leftShoulder, armLeft.Shoulder); AddBoneToSkeleton(HumanoidBones.leftUpperArm, armLeft.UpperArm); AddBoneToSkeleton(HumanoidBones.leftLowerArm, armLeft.LowerArm); AddBoneToSkeleton(HumanoidBones.leftHand, armLeft.Hand); AddBoneToSkeleton(HumanoidBones.rightShoulder, armRight.Shoulder); AddBoneToSkeleton(HumanoidBones.rightUpperArm, armRight.UpperArm); AddBoneToSkeleton(HumanoidBones.rightLowerArm, armRight.LowerArm); AddBoneToSkeleton(HumanoidBones.rightHand, armRight.Hand); return(skeleton); }