示例#1
0
 public static void InitGlobalMappingData()
 {
     if (!s_DidPerformInit)
     {
         List <BoneMappingItem> list = new List <BoneMappingItem>(s_MappingDataBody);
         int count = list.Count;
         for (int i = 0; i < count; i++)
         {
             BoneMappingItem item = list[i];
             if (item.side == Side.Right)
             {
                 int leftBoneIndexFromRight = GetLeftBoneIndexFromRight(item.bone);
                 int parent = GetLeftBoneIndexFromRight(item.parent);
                 list.Add(new BoneMappingItem(parent, leftBoneIndexFromRight, item.minStep, item.maxStep, item.lengthRatio, new Vector3(-item.dir.x, item.dir.y, item.dir.z), Side.Left, item.optional, item.alwaysInclude, item.keywords));
             }
         }
         s_MappingDataBody = list.ToArray();
         for (int j = 0; j < s_MappingDataBody.Length; j++)
         {
             s_MappingDataBody[j].GetChildren(s_MappingDataBody);
         }
         for (int k = 0; k < s_LeftMappingDataHand.Length; k++)
         {
             s_LeftMappingDataHand[k].GetChildren(s_LeftMappingDataHand);
         }
         for (int m = 0; m < s_RightMappingDataHand.Length; m++)
         {
             s_RightMappingDataHand[m].GetChildren(s_RightMappingDataHand);
         }
         s_DidPerformInit = true;
     }
 }
示例#2
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);
        }
        public static void InitGlobalMappingData()
        {
            if (s_DidPerformInit)
            {
                return;
            }

            List <BoneMappingItem> mappingData = new List <BoneMappingItem>(s_MappingDataBody);

            // Add left side bones to match right side ones.
            int size = mappingData.Count;

            for (int i = 0; i < size; i++)
            {
                BoneMappingItem item = mappingData[i];
                if (item.side == Side.Right)
                {
                    // Get left HumanBodyBones that mirrors right one.
                    int bone = GetLeftBoneIndexFromRight(item.bone);
                    // Get left parent HumanBodyBones that mirrors parent of right one
                    int parentBone = GetLeftBoneIndexFromRight(item.parent);
                    // Add left BoneMappingItem that mirrors right one.
                    mappingData.Add(new BoneMappingItem(parentBone, bone, item.minStep, item.maxStep, item.lengthRatio, new Vector3(-item.dir.x, item.dir.y, item.dir.z), Side.Left, item.optional, item.alwaysInclude, item.keywords));
                }
            }

            s_MappingDataBody = mappingData.ToArray();

            // Cache children for each BoneMappingItem
            for (int i = 0; i < s_MappingDataBody.Length; i++)
            {
                s_MappingDataBody[i].GetChildren(s_MappingDataBody);
            }
            for (int i = 0; i < s_LeftMappingDataHand.Length; i++)
            {
                s_LeftMappingDataHand[i].GetChildren(s_LeftMappingDataHand);
            }
            for (int i = 0; i < s_RightMappingDataHand.Length; i++)
            {
                s_RightMappingDataHand[i].GetChildren(s_RightMappingDataHand);
            }

            s_DidPerformInit = true;
        }
        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;
            }
        }
        // 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);
        }
 public BoneMatch(BoneMatch parent, Transform bone, BoneMappingItem item)
 {
     this.parent = parent;
     this.bone   = bone;
     this.item   = item;
 }
示例#8
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);
        }
示例#9
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;
            }
        }