Esempio n. 1
0
        private void ScoreBoneMatch(BoneMatch match)
        {
            int num = this.BoneHasBadKeyword(match.bone, match.item.keywords);

            match.score += num;
            if (kDebug && (num != 0))
            {
                match.debugTracker.Add(string.Concat(new object[] { num, ": ", this.GetMatchString(match), " matched bad keywords" }));
            }
            if (num >= 0)
            {
                int num2 = this.BoneHasKeyword(match.bone, match.item.keywords);
                match.score += num2;
                if (kDebug && (num2 != 0))
                {
                    match.debugTracker.Add(string.Concat(new object[] { num2, ": ", this.GetMatchString(match), " matched keywords" }));
                }
                if ((match.item.keywords.Length == 0) && match.item.alwaysInclude)
                {
                    match.score++;
                    if (kDebug)
                    {
                        match.debugTracker.Add(string.Concat(new object[] { 1, ": ", this.GetMatchString(match), " always-include point" }));
                    }
                }
            }
        }
        private void ScoreBoneMatch(BoneMatch match)
        {
            int badKeywordScore = BoneHasBadKeyword(match.bone, match.item.keywords);

            match.score += badKeywordScore;
            if (kDebug && badKeywordScore != 0)
            {
                match.debugTracker.Add(badKeywordScore + ": " + GetMatchString(match) + " matched bad keywords");
            }
            if (badKeywordScore < 0)
            {
                return;
            }

            int keywordScore = BoneHasKeyword(match.bone, match.item.keywords);

            match.score += keywordScore;
            if (kDebug && keywordScore != 0)
            {
                match.debugTracker.Add(keywordScore + ": " + GetMatchString(match) + " matched keywords");
            }

            // If child bone with no required keywords, give a minimal score so it can still be included in mapping
            if (match.item.keywords.Length == 0 && match.item.alwaysInclude)
            {
                match.score += 1;
                if (kDebug)
                {
                    match.debugTracker.Add(1 + ": " + GetMatchString(match) + " always-include point");
                }
            }
        }
        private int GetBoneSideMatchPoints(BoneMatch match)
        {
            string boneName = match.bone.name;

            if (match.item.side == Side.None)
            {
                if (MatchesSideKeywords(boneName, false) || MatchesSideKeywords(boneName, true))
                {
                    return(-1000);
                }
            }

            bool left = (match.item.side == Side.Left);

            if (MatchesSideKeywords(boneName, left))
            {
                return(15);
            }
            if (MatchesSideKeywords(boneName, !left))
            {
                return(-1000);
            }

            return(0);
        }
 private void ApplyMapping(BoneMatch match, Dictionary <int, Transform> mapping)
 {
     if (match.doMap)
     {
         mapping[match.item.bone] = match.bone;
     }
     foreach (BoneMatch child in match.children)
     {
         ApplyMapping(child, mapping);
     }
 }
Esempio n. 5
0
        private void MapBonesFromRootDown(BoneMatch rootMatch, Dictionary <int, Transform> mapping)
        {
            List <BoneMatch> list = this.RecursiveFindPotentialBoneMatches(rootMatch, this.m_MappingData[0], true);

            if ((list != null) && (list.Count > 0))
            {
                if (kDebug)
                {
                    this.EvaluateBoneMatch(list[0], true);
                }
                this.ApplyMapping(list[0], mapping);
            }
        }
        private void MapBonesFromRootDown(BoneMatch rootMatch, Dictionary <int, Transform> mapping)
        {
            // Perform mapping
            List <BoneMatch> childMatches = RecursiveFindPotentialBoneMatches(rootMatch, m_MappingData[0], true);

            if (childMatches != null && childMatches.Count > 0)
            {
                if (kDebug)
                {
                    EvaluateBoneMatch(childMatches[0], true);
                }
                ApplyMapping(childMatches[0], mapping);
            }
        }
Esempio n. 7
0
        private int GetMatchKey(BoneMatch parentMatch, Transform t, BoneMappingItem goalItem)
        {
            int num = goalItem.bone + (t.GetInstanceID() * 0x3e8);

            if (parentMatch != null)
            {
                num += parentMatch.bone.GetInstanceID() * 0xf4240;
                if (parentMatch.parent != null)
                {
                    num += parentMatch.parent.bone.GetInstanceID() * 0x3b9aca00;
                }
            }
            return(num);
        }
        private int GetMatchKey(BoneMatch parentMatch, Transform t, BoneMappingItem goalItem)
        {
            SimpleProfiler.Begin("GetMatchKey");
            int key = goalItem.bone;

            key += t.GetInstanceID() * 1000;
            if (parentMatch != null)
            {
                key += parentMatch.bone.GetInstanceID() * 1000000;
                if (parentMatch.parent != null)
                {
                    key += parentMatch.parent.bone.GetInstanceID() * 1000000000;
                }
            }
            SimpleProfiler.End();
            return(key);
        }
Esempio n. 9
0
        private int GetBoneSideMatchPoints(BoneMatch match)
        {
            string name = match.bone.name;

            if ((match.item.side == Side.None) && (this.MatchesSideKeywords(name, false) || this.MatchesSideKeywords(name, true)))
            {
                return(-1000);
            }
            bool left = match.item.side == Side.Left;

            if (this.MatchesSideKeywords(name, left))
            {
                return(15);
            }
            if (this.MatchesSideKeywords(name, !left))
            {
                return(-1000);
            }
            return(0);
        }
Esempio n. 10
0
        private List <BoneMatch> GetBestChildMatches(BoneMatch parentMatch, List <List <BoneMatch> > childMatchesLists)
        {
            float            num;
            List <BoneMatch> list = new List <BoneMatch>();

            if (childMatchesLists.Count == 1)
            {
                list.Add(childMatchesLists[0][0]);
                return(list);
            }
            int[] choices = new int[childMatchesLists.Count];
            choices = this.GetBestChildMatchChoices(parentMatch, childMatchesLists, choices, out num);
            for (int i = 0; i < choices.Length; i++)
            {
                if (choices[i] >= 0)
                {
                    list.Add(childMatchesLists[i][choices[i]]);
                }
            }
            return(list);
        }
        private List <BoneMatch> GetBestChildMatches(BoneMatch parentMatch, List <List <BoneMatch> > childMatchesLists)
        {
            List <BoneMatch> bestMatches = new List <BoneMatch>();

            if (childMatchesLists.Count == 1)
            {
                bestMatches.Add(childMatchesLists[0][0]);
                return(bestMatches);
            }

            int[] choices = new int[childMatchesLists.Count];
            float dummyScore;

            choices = GetBestChildMatchChoices(parentMatch, childMatchesLists, choices, out dummyScore);
            for (int i = 0; i < choices.Length; i++)
            {
                if (choices[i] >= 0)
                {
                    bestMatches.Add(childMatchesLists[i][choices[i]]);
                }
            }
            return(bestMatches);
        }
Esempio n. 12
0
        private int[] GetBestChildMatchChoices(BoneMatch parentMatch, List <List <BoneMatch> > childMatchesLists, int[] choices, out float score)
        {
            List <int> list = new List <int>();

            for (int i = 0; i < choices.Length; i++)
            {
                if (choices[i] >= 0)
                {
                    list.Clear();
                    list.Add(i);
                    for (int k = i + 1; k < choices.Length; k++)
                    {
                        if ((choices[k] >= 0) && this.ShareTransformPath(parentMatch.bone, childMatchesLists[i][choices[i]].bone, childMatchesLists[k][choices[k]].bone))
                        {
                            list.Add(k);
                        }
                    }
                    if (list.Count > 1)
                    {
                        break;
                    }
                }
            }
            if (list.Count <= 1)
            {
                score = 0f;
                for (int m = 0; m < choices.Length; m++)
                {
                    if (choices[m] >= 0)
                    {
                        score += childMatchesLists[m][choices[m]].totalSiblingScore;
                    }
                }
                return(choices);
            }
            float num4 = 0f;

            int[] numArray2 = choices;
            for (int j = 0; j < list.Count; j++)
            {
                float num7;
                int[] destinationArray = new int[choices.Length];
                Array.Copy(choices, destinationArray, choices.Length);
                for (int n = 0; n < list.Count; n++)
                {
                    if (j != n)
                    {
                        if (list[n] >= destinationArray.Length)
                        {
                            Debug.LogError(string.Concat(new object[] { "sharedIndices[j] (", list[n], ") >= altChoices.Length (", destinationArray.Length, ")" }));
                        }
                        if (list[n] >= childMatchesLists.Count)
                        {
                            Debug.LogError(string.Concat(new object[] { "sharedIndices[j] (", list[n], ") >= childMatchesLists.Count (", childMatchesLists.Count, ")" }));
                        }
                        if (destinationArray[list[n]] < (childMatchesLists[list[n]].Count - 1))
                        {
                            destinationArray[list[n]]++;
                        }
                        else
                        {
                            destinationArray[list[n]] = -1;
                        }
                    }
                }
                destinationArray = this.GetBestChildMatchChoices(parentMatch, childMatchesLists, destinationArray, out num7);
                if (num7 > num4)
                {
                    num4      = num7;
                    numArray2 = destinationArray;
                }
            }
            score = num4;
            return(numArray2);
        }
        // Returns possible matches sorted with best-scoring ones first in the list
        private List <BoneMatch> RecursiveFindPotentialBoneMatches(BoneMatch parentMatch, BoneMappingItem goalItem, bool confirmedChoice)
        {
            List <BoneMatch> matches = new List <BoneMatch>();

            // We want to search with breadh first search so we have to use a queue
            Queue <QueuedBone> queue = new Queue <QueuedBone>();

            // Find matches
            queue.Enqueue(new QueuedBone(parentMatch.bone, 0));
            while (queue.Count > 0)
            {
                QueuedBone current = queue.Dequeue();
                Transform  t       = current.bone;
                if (current.level >= goalItem.minStep && (m_TreatDummyBonesAsReal || m_ValidBones == null || (m_ValidBones.ContainsKey(t) && m_ValidBones[t])))
                {
                    BoneMatch match;
                    var       key = GetMatchKey(parentMatch, t, goalItem);
                    if (m_BoneMatchDict.ContainsKey(key))
                    {
                        match = m_BoneMatchDict[key];
                    }
                    else
                    {
                        match = new BoneMatch(parentMatch, t, goalItem);

                        // RECURSIVE CALL
                        EvaluateBoneMatch(match, false);
                        m_BoneMatchDict[key] = match;
                    }

                    if (match.score > 0 || kDebug)
                    {
                        matches.Add(match);
                    }
                }
                SimpleProfiler.Begin("Queue");
                if (current.level < goalItem.maxStep)
                {
                    foreach (Transform child in t)
                    {
                        if (m_ValidBones == null || m_ValidBones.ContainsKey(child))
                        {
                            if (!m_TreatDummyBonesAsReal && m_ValidBones != null && !m_ValidBones[child])
                            {
                                queue.Enqueue(new QueuedBone(child, current.level));
                            }
                            else
                            {
                                queue.Enqueue(new QueuedBone(child, current.level + 1));
                            }
                        }
                    }
                }
                SimpleProfiler.End();
            }

            if (matches.Count == 0)
            {
                return(null);
            }

            // Sort by match score with best matches first
            SimpleProfiler.Begin("SortAndTrim");
            matches.Sort();
            if (matches[0].score <= 0)
            {
                return(null);
            }

            if (kDebug && confirmedChoice)
            {
                DebugMatchChoice(matches);
            }

            // Keep top 3 priorities only for optimization
            while (matches.Count > 3)
            {
                matches.RemoveAt(matches.Count - 1);
            }
            matches.TrimExcess();
            SimpleProfiler.End();

            return(matches);
        }
 private string GetMatchString(BoneMatch match)
 {
     return(GetNameOfBone(match.item.bone) + ":" + (match.bone == null ? "null" : match.bone.name));
 }
Esempio n. 15
0
 private string GetMatchString(BoneMatch match) =>
 (this.GetNameOfBone(match.item.bone) + ":" + ((match.bone != null) ? match.bone.name : "null"));
Esempio n. 16
0
        public Dictionary <int, Transform> MapBones(Transform root)
        {
            InitGlobalMappingData();
            Dictionary <int, Transform> mapping = new Dictionary <int, Transform>();

            this.m_Orientation        = Quaternion.identity;
            this.m_MappingData        = s_MappingDataBody;
            this.m_MappingIndexOffset = 0;
            this.m_BoneMatchDict.Clear();
            BoneMatch rootMatch = new BoneMatch(null, root, this.m_MappingData[0]);

            this.m_TreatDummyBonesAsReal = false;
            this.MapBonesFromRootDown(rootMatch, mapping);
            if (mapping.Count < 15)
            {
                this.m_TreatDummyBonesAsReal = true;
                this.MapBonesFromRootDown(rootMatch, mapping);
            }
            if ((mapping.ContainsKey(1) && mapping.ContainsKey(2)) && (mapping.ContainsKey(13) && mapping.ContainsKey(14)))
            {
                this.m_Orientation = AvatarSetupTool.AvatarComputeOrientation(mapping[1].position, mapping[2].position, mapping[13].position, mapping[14].position);
                if ((Vector3.Angle((Vector3)(this.m_Orientation * Vector3.up), Vector3.up) > 20f) || (Vector3.Angle((Vector3)(this.m_Orientation * Vector3.forward), Vector3.forward) > 20f))
                {
                    if (kDebug)
                    {
                        Debug.Log("*** Mapping with new computed orientation");
                    }
                    mapping.Clear();
                    this.m_BoneMatchDict.Clear();
                    this.MapBonesFromRootDown(rootMatch, mapping);
                }
            }
            if ((!(!this.m_ValidBones.ContainsKey(root) ? false : this.m_ValidBones[root]) && (mapping.Count > 0)) && mapping.ContainsKey(0))
            {
                while (true)
                {
                    Transform parent = mapping[0].parent;
                    if (((parent == null) || (parent == rootMatch.bone)) || (!this.m_ValidBones.ContainsKey(parent) || !this.m_ValidBones[parent]))
                    {
                        break;
                    }
                    mapping[0] = parent;
                }
            }
            int        num         = 3;
            Quaternion orientation = this.m_Orientation;

            if (mapping.ContainsKey(0x11))
            {
                Transform bone       = mapping[15];
                Transform transform3 = mapping[0x11];
                this.m_Orientation        = Quaternion.FromToRotation((Vector3)(orientation * -Vector3.right), transform3.position - bone.position) * orientation;
                this.m_MappingData        = s_LeftMappingDataHand;
                this.m_MappingIndexOffset = 0x18;
                this.m_BoneMatchDict.Clear();
                BoneMatch match2 = new BoneMatch(null, bone, this.m_MappingData[0]);
                this.m_TreatDummyBonesAsReal = true;
                int count = mapping.Count;
                this.MapBonesFromRootDown(match2, mapping);
                if (mapping.Count < (count + num))
                {
                    for (int i = 0x18; i <= 0x26; i++)
                    {
                        mapping.Remove(i);
                    }
                }
            }
            if (mapping.ContainsKey(0x12))
            {
                Transform transform4 = mapping[0x10];
                Transform transform5 = mapping[0x12];
                this.m_Orientation        = Quaternion.FromToRotation((Vector3)(orientation * Vector3.right), transform5.position - transform4.position) * orientation;
                this.m_MappingData        = s_RightMappingDataHand;
                this.m_MappingIndexOffset = 0x27;
                this.m_BoneMatchDict.Clear();
                BoneMatch match3 = new BoneMatch(null, transform4, this.m_MappingData[0]);
                this.m_TreatDummyBonesAsReal = true;
                int num4 = mapping.Count;
                this.MapBonesFromRootDown(match3, mapping);
                if (mapping.Count >= (num4 + num))
                {
                    return(mapping);
                }
                for (int j = 0x27; j <= 0x35; j++)
                {
                    mapping.Remove(j);
                }
            }
            return(mapping);
        }
Esempio n. 17
0
        private List <BoneMatch> RecursiveFindPotentialBoneMatches(BoneMatch parentMatch, BoneMappingItem goalItem, bool confirmedChoice)
        {
            List <BoneMatch>   matches = new List <BoneMatch>();
            Queue <QueuedBone> queue   = new Queue <QueuedBone>();

            queue.Enqueue(new QueuedBone(parentMatch.bone, 0));
            while (queue.Count > 0)
            {
                QueuedBone bone = queue.Dequeue();
                Transform  key  = bone.bone;
                if ((bone.level >= goalItem.minStep) && ((this.m_TreatDummyBonesAsReal || (this.m_ValidBones == null)) || (this.m_ValidBones.ContainsKey(key) && this.m_ValidBones[key])))
                {
                    BoneMatch match;
                    int       num = this.GetMatchKey(parentMatch, key, goalItem);
                    if (this.m_BoneMatchDict.ContainsKey(num))
                    {
                        match = this.m_BoneMatchDict[num];
                    }
                    else
                    {
                        match = new BoneMatch(parentMatch, key, goalItem);
                        this.EvaluateBoneMatch(match, false);
                        this.m_BoneMatchDict[num] = match;
                    }
                    if ((match.score > 0f) || kDebug)
                    {
                        matches.Add(match);
                    }
                }
                if (bone.level < goalItem.maxStep)
                {
                    IEnumerator enumerator = key.GetEnumerator();
                    try
                    {
                        while (enumerator.MoveNext())
                        {
                            Transform current = (Transform)enumerator.Current;
                            if ((this.m_ValidBones == null) || this.m_ValidBones.ContainsKey(current))
                            {
                                if ((!this.m_TreatDummyBonesAsReal && (this.m_ValidBones != null)) && !this.m_ValidBones[current])
                                {
                                    queue.Enqueue(new QueuedBone(current, bone.level));
                                }
                                else
                                {
                                    queue.Enqueue(new QueuedBone(current, bone.level + 1));
                                }
                            }
                        }
                    }
                    finally
                    {
                        IDisposable disposable = enumerator as IDisposable;
                        if (disposable != null)
                        {
                            disposable.Dispose();
                        }
                    }
                }
            }
            if (matches.Count == 0)
            {
                return(null);
            }
            matches.Sort();
            if (matches[0].score <= 0f)
            {
                return(null);
            }
            if (kDebug && confirmedChoice)
            {
                this.DebugMatchChoice(matches);
            }
            while (matches.Count > 3)
            {
                matches.RemoveAt(matches.Count - 1);
            }
            matches.TrimExcess();
            return(matches);
        }
        private int[] GetBestChildMatchChoices(BoneMatch parentMatch, List <List <BoneMatch> > childMatchesLists, int[] choices, out float score)
        {
            // See if any choices share the same transform path.
            List <int> sharedIndices = new List <int>();

            for (int i = 0; i < choices.Length; i++)
            {
                if (choices[i] < 0)
                {
                    continue;
                }
                sharedIndices.Clear();
                sharedIndices.Add(i);
                for (int j = i + 1; j < choices.Length; j++)
                {
                    if (choices[j] < 0)
                    {
                        continue;
                    }
                    if (ShareTransformPath(parentMatch.bone, childMatchesLists[i][choices[i]].bone, childMatchesLists[j][choices[j]].bone))
                    {
                        sharedIndices.Add(j);
                    }
                }

                if (sharedIndices.Count > 1)
                {
                    break;
                }
            }

            if (sharedIndices.Count <= 1)
            {
                // If no shared transform paths, calculate score and return choices.
                score = 0;
                for (int i = 0; i < choices.Length; i++)
                {
                    if (choices[i] >= 0)
                    {
                        score += childMatchesLists[i][choices[i]].totalSiblingScore;
                    }
                }
                return(choices);
            }
            else
            {
                // If transform paths are shared by multiple choices, call function recursively.
                float bestScore   = 0;
                int[] bestChoices = choices;
                for (int i = 0; i < sharedIndices.Count; i++)
                {
                    int[] altChoices = new int[choices.Length];
                    Array.Copy(choices, altChoices, choices.Length);
                    // In each call, one of the choices retains their priority while the remaining are bumped one priority down.
                    for (int j = 0; j < sharedIndices.Count; j++)
                    {
                        if (i != j)
                        {
                            if (sharedIndices[j] >= altChoices.Length)
                            {
                                Debug.LogError("sharedIndices[j] (" + sharedIndices[j] + ") >= altChoices.Length (" + altChoices.Length + ")");
                            }
                            if (sharedIndices[j] >= childMatchesLists.Count)
                            {
                                Debug.LogError("sharedIndices[j] (" + sharedIndices[j] + ") >= childMatchesLists.Count (" + childMatchesLists.Count + ")");
                            }
                            if (altChoices[sharedIndices[j]] < childMatchesLists[sharedIndices[j]].Count - 1)
                            {
                                altChoices[sharedIndices[j]]++;
                            }
                            else
                            {
                                altChoices[sharedIndices[j]] = -1;
                            }
                        }
                    }
                    float altScore;
                    altChoices = GetBestChildMatchChoices(parentMatch, childMatchesLists, altChoices, out altScore);
                    if (altScore > bestScore)
                    {
                        bestScore   = altScore;
                        bestChoices = altChoices;
                    }
                }
                // Return the choices with the best score
                score = bestScore;
                return(bestChoices);
            }
        }
        public Dictionary <int, Transform> MapBones(Transform root)
        {
            InitGlobalMappingData();

            Dictionary <int, Transform> mapping = new Dictionary <int, Transform>();

            // Perform body mapping
            {
                m_Orientation        = Quaternion.identity;
                m_MappingData        = s_MappingDataBody;
                m_MappingIndexOffset = 0;
                m_BoneMatchDict.Clear();
                BoneMatch rootMatch = new BoneMatch(null, root, m_MappingData[0]);

                m_TreatDummyBonesAsReal = false;
                MapBonesFromRootDown(rootMatch, mapping);
                // There are 15 required bones. If we mapped less than that, check if we can do better.
                if (mapping.Count < 15)
                {
                    m_TreatDummyBonesAsReal = true;
                    MapBonesFromRootDown(rootMatch, mapping);
                }

                // Check if character has correct alignment
                if (mapping.ContainsKey((int)HumanBodyBones.LeftUpperLeg) && mapping.ContainsKey((int)HumanBodyBones.RightUpperLeg) &&
                    mapping.ContainsKey((int)HumanBodyBones.LeftUpperArm) && mapping.ContainsKey((int)HumanBodyBones.RightUpperArm))
                {
                    m_Orientation = AvatarSetupTool.AvatarComputeOrientation(
                        mapping[(int)HumanBodyBones.LeftUpperLeg].position, mapping[(int)HumanBodyBones.RightUpperLeg].position,
                        mapping[(int)HumanBodyBones.LeftUpperArm].position, mapping[(int)HumanBodyBones.RightUpperArm].position);

                    // If not standard aligned, try to map again with correct alignment assumptions
                    if (Vector3.Angle(m_Orientation * Vector3.up, Vector3.up) > 20 || Vector3.Angle(m_Orientation * Vector3.forward, Vector3.forward) > 20)
                    {
                        if (kDebug)
                        {
                            Debug.Log("*** Mapping with new computed orientation");
                        }
                        mapping.Clear();
                        m_BoneMatchDict.Clear();
                        MapBonesFromRootDown(rootMatch, mapping);
                    }
                }

                // For models that don't have meshes, all bones are marked valid; even the root.
                // So we use this to check if this model has meshes or not.
                bool modelHasMeshes = !(m_ValidBones.ContainsKey(root) && m_ValidBones[root] == true);

                // Fix up hips to be valid bone closest to the root
                // For models with meshes, valid bones further up are mapped to part of the mesh (otherwise they wouldn't be valid).
                // For models with no meshes we don't know which transforms are valid bones and which aren't
                // so we skip this step and use the found hips bone as-is.
                if (modelHasMeshes && mapping.Count > 0 && mapping.ContainsKey((int)HumanBodyBones.Hips))
                {
                    while (true)
                    {
                        Transform parent = mapping[(int)HumanBodyBones.Hips].parent;
                        if (parent != null && parent != rootMatch.bone && m_ValidBones.ContainsKey(parent) && m_ValidBones[parent] == true)
                        {
                            mapping[(int)HumanBodyBones.Hips] = parent;
                        }
                        else
                        {
                            break;
                        }
                    }
                }

                // Move upper chest to chest if no chest was found
                if (!mapping.ContainsKey((int)HumanBodyBones.Chest) &&
                    mapping.ContainsKey((int)HumanBodyBones.UpperChest))
                {
                    mapping.Add((int)HumanBodyBones.Chest, mapping[(int)HumanBodyBones.UpperChest]);
                    mapping.Remove((int)HumanBodyBones.UpperChest);
                }
            }

            int kMinFingerBones = 3;

            Quaternion bodyOrientation = m_Orientation;

            // Perform left hand mapping
            if (mapping.ContainsKey((int)HumanBodyBones.LeftHand))
            {
                Transform lowerArm = mapping[(int)HumanBodyBones.LeftLowerArm];
                Transform hand     = mapping[(int)HumanBodyBones.LeftHand];

                // Use reference orientation based on lower arm for mapping hand
                m_Orientation = Quaternion.FromToRotation(bodyOrientation * -Vector3.right, hand.position - lowerArm.position) * bodyOrientation;

                m_MappingData        = s_LeftMappingDataHand;
                m_MappingIndexOffset = (int)HumanBodyBones.LeftThumbProximal;
                m_BoneMatchDict.Clear();
                BoneMatch rootMatch = new BoneMatch(null, lowerArm, m_MappingData[0]);
                m_TreatDummyBonesAsReal = true;

                int mappingCountBefore = mapping.Count;
                MapBonesFromRootDown(rootMatch, mapping);

                // If we only mapped 2 finger bones or less, then cancel mapping of fingers
                if (mapping.Count < mappingCountBefore + kMinFingerBones)
                {
                    for (int i = (int)HumanBodyBones.LeftThumbProximal; i <= (int)HumanBodyBones.LeftLittleDistal; i++)
                    {
                        mapping.Remove(i);
                    }
                }
            }

            // Perform right hand mapping
            if (mapping.ContainsKey((int)HumanBodyBones.RightHand))
            {
                Transform lowerArm = mapping[(int)HumanBodyBones.RightLowerArm];
                Transform hand     = mapping[(int)HumanBodyBones.RightHand];

                // Use reference orientation based on lower arm for mapping hand
                m_Orientation = Quaternion.FromToRotation(bodyOrientation * Vector3.right, hand.position - lowerArm.position) * bodyOrientation;

                m_MappingData        = s_RightMappingDataHand;
                m_MappingIndexOffset = (int)HumanBodyBones.RightThumbProximal;
                m_BoneMatchDict.Clear();
                BoneMatch rootMatch = new BoneMatch(null, lowerArm, m_MappingData[0]);
                m_TreatDummyBonesAsReal = true;

                int mappingCountBefore = mapping.Count;
                MapBonesFromRootDown(rootMatch, mapping);

                // If we only mapped 2 finger bones or less, then cancel mapping of fingers
                if (mapping.Count < mappingCountBefore + kMinFingerBones)
                {
                    for (int i = (int)HumanBodyBones.RightThumbProximal; i <= (int)HumanBodyBones.RightLittleDistal; i++)
                    {
                        mapping.Remove(i);
                    }
                }
            }

            return(mapping);
        }
        private void EvaluateBoneMatch(BoneMatch match, bool confirmedChoice)
        {
            match.score        = 0;
            match.siblingScore = 0;

            // Things to copy from identical match: score, siblingScore, children, doMap

            // Iterate child BoneMappingitems
            List <List <BoneMatch> > childMatchesLists = new List <List <BoneMatch> >();
            int intendedChildCount = 0;

            foreach (int c in match.item.GetChildren(m_MappingData))
            {
                BoneMappingItem i = m_MappingData[c];
                if (i.parent == match.item.bone)
                {
                    intendedChildCount++;
                    // RECURSIVE CALL
                    List <BoneMatch> childMatches = RecursiveFindPotentialBoneMatches(match, i, confirmedChoice);
                    if (childMatches == null || childMatches.Count == 0)
                    {
                        continue;
                    }
                    childMatchesLists.Add(childMatches);
                }
            }

            // Best best child matches
            bool sameAsParentOrChild = (match.bone == match.humanBoneParent.bone);

            if (childMatchesLists.Count > 0)
            {
                SimpleProfiler.Begin("GetBestChildMatches");
                match.children = GetBestChildMatches(match, childMatchesLists);
                SimpleProfiler.End();

                // Handle child matches
                foreach (BoneMatch childMatch in match.children)
                {
                    // RECURSIVE CALL for debugging purposes
                    if (kDebug && confirmedChoice)
                    {
                        EvaluateBoneMatch(childMatch, confirmedChoice);
                    }

                    // Transfer info from best child match to parent
                    match.score += childMatch.score;
                    if (kDebug)
                    {
                        match.debugTracker.AddRange(childMatch.debugTracker);
                    }
                    if (childMatch.bone == match.bone && childMatch.item.bone >= 0)
                    {
                        sameAsParentOrChild = true;
                    }
                }
            }

            SimpleProfiler.Begin("ScoreBoneMatch");
            // Keyword score the bone if it's not optional or if it's different from both parent bone and all child bones
            if (!match.item.optional || !sameAsParentOrChild)
            {
                ScoreBoneMatch(match);
            }
            SimpleProfiler.End();

            // Rate bone according to how well it matches goal direction
            SimpleProfiler.Begin("MatchesDir");
            if (match.item.dir != Vector3.zero)
            {
                Vector3 goalDir = match.item.dir;
                if (m_MappingIndexOffset >= (int)HumanBodyBones.LeftThumbProximal && m_MappingIndexOffset < (int)HumanBodyBones.RightThumbProximal)
                {
                    goalDir.x *= -1;
                }
                Vector3 dir = (match.bone.position - match.humanBoneParent.bone.position).normalized;
                dir = Quaternion.Inverse(m_Orientation) * dir;
                float dirMatchingScore = Vector3.Dot(dir, goalDir) * (match.item.optional ? 5 : 10);

                match.siblingScore += dirMatchingScore;
                if (kDebug)
                {
                    match.debugTracker.Add("* " + dirMatchingScore + ": " + GetMatchString(match) + " matched dir (" + (match.bone.position - match.humanBoneParent.bone.position).normalized + " , " + goalDir + ")");
                }

                if (dirMatchingScore > 0)
                {
                    match.score += 10;
                    if (kDebug)
                    {
                        match.debugTracker.Add(10 + ": " + GetMatchString(match) + " matched dir (" + (match.bone.position - match.humanBoneParent.bone.position).normalized + " , " + goalDir + ")");
                    }
                }
            }
            SimpleProfiler.End();

            // Give small score if bone matches side it belongs to.
            SimpleProfiler.Begin("MatchesSide");
            if (m_MappingIndexOffset == 0)
            {
                int sideMatchingScore = GetBoneSideMatchPoints(match);
                if (match.parent.item.side == Side.None || sideMatchingScore < 0)
                {
                    match.siblingScore += sideMatchingScore;
                    if (kDebug)
                    {
                        match.debugTracker.Add("* " + sideMatchingScore + ": " + GetMatchString(match) + " matched side");
                    }
                }
            }
            SimpleProfiler.End();

            // These criteria can not push a bone above the threshold, but they can help to break ties.
            if (match.score > 0)
            {
                // Reward optional bones being included
                if (match.item.optional && !sameAsParentOrChild)
                {
                    match.score += 5;
                    if (kDebug)
                    {
                        match.debugTracker.Add(5 + ": " + GetMatchString(match) + " optional bone is included");
                    }
                }

                // Handle end bones
                if (intendedChildCount == 0 && match.bone.childCount > 0)
                {
                    // Reward end bones having a dummy child transform
                    match.score += 1;
                    if (kDebug)
                    {
                        match.debugTracker.Add(1 + ": " + GetMatchString(match) + " has dummy child bone");
                    }
                }

                // Give score to bones length ratio according to match with goal ratio.
                SimpleProfiler.Begin("LengthRatio");
                if (match.item.lengthRatio != 0)
                {
                    float parentLength = Vector3.Distance(match.bone.position, match.humanBoneParent.bone.position);
                    if (parentLength == 0 && match.bone != match.humanBoneParent.bone)
                    {
                        match.score -= 1000;
                        if (kDebug)
                        {
                            match.debugTracker.Add((-1000) + ": " + GetMatchString(match.humanBoneParent) + " has zero length");
                        }
                    }

                    float grandParentLength = Vector3.Distance(match.humanBoneParent.bone.position, match.humanBoneParent.humanBoneParent.bone.position);
                    if (grandParentLength > 0)
                    {
                        float logRatio     = Mathf.Log(parentLength / grandParentLength, 2);
                        float logGoalRatio = Mathf.Log(match.item.lengthRatio, 2);
                        float ratioScore   = 10 * Mathf.Clamp(1 - 0.6f * Mathf.Abs(logRatio - logGoalRatio), 0, 1);
                        match.score += ratioScore;
                        if (kDebug)
                        {
                            match.debugTracker.Add(ratioScore + ": parent " + GetMatchString(match.humanBoneParent) + " matched lengthRatio - " + parentLength + " / " + grandParentLength + " = " + (parentLength / grandParentLength) + " (" + logRatio + ") goal: " + match.item.lengthRatio + " (" + logGoalRatio + ")");
                        }
                    }
                }
                SimpleProfiler.End();
            }

            // Only map optional bones if they're not the same as the parent or child.
            if (match.item.bone >= 0 && (!match.item.optional || !sameAsParentOrChild))
            {
                match.doMap = true;
            }
        }
Esempio n. 21
0
        private void EvaluateBoneMatch(BoneMatch match, bool confirmedChoice)
        {
            match.score        = 0f;
            match.siblingScore = 0f;
            List <List <BoneMatch> > childMatchesLists = new List <List <BoneMatch> >();
            int num = 0;

            foreach (int num2 in match.item.GetChildren(this.m_MappingData))
            {
                BoneMappingItem goalItem = this.m_MappingData[num2];
                if (goalItem.parent == match.item.bone)
                {
                    num++;
                    List <BoneMatch> item = this.RecursiveFindPotentialBoneMatches(match, goalItem, confirmedChoice);
                    if ((item != null) && (item.Count != 0))
                    {
                        childMatchesLists.Add(item);
                    }
                }
            }
            bool flag = match.bone == match.humanBoneParent.bone;
            int  num4 = 0;

            if (childMatchesLists.Count > 0)
            {
                match.children = this.GetBestChildMatches(match, childMatchesLists);
                foreach (BoneMatch match2 in match.children)
                {
                    if (kDebug && confirmedChoice)
                    {
                        this.EvaluateBoneMatch(match2, confirmedChoice);
                    }
                    num4++;
                    match.score += match2.score;
                    if (kDebug)
                    {
                        match.debugTracker.AddRange(match2.debugTracker);
                    }
                    if ((match2.bone == match.bone) && (match2.item.bone >= 0))
                    {
                        flag = true;
                    }
                }
            }
            if (!match.item.optional || !flag)
            {
                this.ScoreBoneMatch(match);
            }
            if (match.item.dir != Vector3.zero)
            {
                Vector3 dir = match.item.dir;
                if ((this.m_MappingIndexOffset >= 0x18) && (this.m_MappingIndexOffset < 0x27))
                {
                    dir.x *= -1f;
                }
                Vector3 vector3    = match.bone.position - match.humanBoneParent.bone.position;
                Vector3 normalized = vector3.normalized;
                normalized = (Vector3)(Quaternion.Inverse(this.m_Orientation) * normalized);
                float num5 = Vector3.Dot(normalized, dir) * (!match.item.optional ? ((float)10) : ((float)5));
                match.siblingScore += num5;
                if (kDebug)
                {
                    object[] objArray1 = new object[9];
                    objArray1[0] = "* ";
                    objArray1[1] = num5;
                    objArray1[2] = ": ";
                    objArray1[3] = this.GetMatchString(match);
                    objArray1[4] = " matched dir (";
                    Vector3 vector4 = match.bone.position - match.humanBoneParent.bone.position;
                    objArray1[5] = vector4.normalized;
                    objArray1[6] = " , ";
                    objArray1[7] = dir;
                    objArray1[8] = ")";
                    match.debugTracker.Add(string.Concat(objArray1));
                }
                if (num5 > 0f)
                {
                    match.score += 10f;
                    if (kDebug)
                    {
                        object[] objArray2 = new object[8];
                        objArray2[0] = 10;
                        objArray2[1] = ": ";
                        objArray2[2] = this.GetMatchString(match);
                        objArray2[3] = " matched dir (";
                        Vector3 vector5 = match.bone.position - match.humanBoneParent.bone.position;
                        objArray2[4] = vector5.normalized;
                        objArray2[5] = " , ";
                        objArray2[6] = dir;
                        objArray2[7] = ")";
                        match.debugTracker.Add(string.Concat(objArray2));
                    }
                }
            }
            if (this.m_MappingIndexOffset == 0)
            {
                int boneSideMatchPoints = this.GetBoneSideMatchPoints(match);
                if ((match.parent.item.side == Side.None) || (boneSideMatchPoints < 0))
                {
                    match.siblingScore += boneSideMatchPoints;
                    if (kDebug)
                    {
                        match.debugTracker.Add(string.Concat(new object[] { "* ", boneSideMatchPoints, ": ", this.GetMatchString(match), " matched side" }));
                    }
                }
            }
            if (match.score > 0f)
            {
                if (match.item.optional && !flag)
                {
                    match.score += 5f;
                    if (kDebug)
                    {
                        match.debugTracker.Add(string.Concat(new object[] { 5, ": ", this.GetMatchString(match), " optional bone is included" }));
                    }
                }
                if ((num == 0) && (match.bone.childCount > 0))
                {
                    match.score++;
                    if (kDebug)
                    {
                        match.debugTracker.Add(string.Concat(new object[] { 1, ": ", this.GetMatchString(match), " has dummy child bone" }));
                    }
                }
                if (match.item.lengthRatio != 0f)
                {
                    float num7 = Vector3.Distance(match.bone.position, match.humanBoneParent.bone.position);
                    if ((num7 == 0f) && (match.bone != match.humanBoneParent.bone))
                    {
                        match.score -= 1000f;
                        if (kDebug)
                        {
                            match.debugTracker.Add(string.Concat(new object[] { -1000, ": ", this.GetMatchString(match.humanBoneParent), " has zero length" }));
                        }
                    }
                    float num8 = Vector3.Distance(match.humanBoneParent.bone.position, match.humanBoneParent.humanBoneParent.bone.position);
                    if (num8 > 0f)
                    {
                        float num9  = Mathf.Log(num7 / num8, 2f);
                        float num10 = Mathf.Log(match.item.lengthRatio, 2f);
                        float num11 = 10f * Mathf.Clamp((float)(1f - (0.6f * Mathf.Abs((float)(num9 - num10)))), (float)0f, (float)1f);
                        match.score += num11;
                        if (kDebug)
                        {
                            match.debugTracker.Add(string.Concat(new object[] { num11, ": parent ", this.GetMatchString(match.humanBoneParent), " matched lengthRatio - ", num7, " / ", num8, " = ", num7 / num8, " (", num9, ") goal: ", match.item.lengthRatio, " (", num10, ")" }));
                        }
                    }
                }
            }
            if ((match.item.bone >= 0) && (!match.item.optional || !flag))
            {
                match.doMap = true;
            }
        }