Пример #1
0
        private void InsertLeaf(int leaf)
        {
            if (_root == NullNode)
            {
                _root = leaf;
                _nodes[_root].ParentOrNext = NullNode;
                return;
            }

            // Find the best sibling for this node
            AABB leafAABB = _nodes[leaf].AABB;
            int  index    = _root;

            while (_nodes[index].IsLeaf() == false)
            {
                int child1 = _nodes[index].Child1;
                int child2 = _nodes[index].Child2;

                float area = _nodes[index].AABB.Perimeter;

                AABB combinedAABB = new AABB();
                combinedAABB.Combine(ref _nodes[index].AABB, ref leafAABB);
                float combinedArea = combinedAABB.Perimeter;

                // Cost of creating a new parent for this node and the new leaf
                float cost = 2.0f * combinedArea;

                // Minimum cost of pushing the leaf further down the tree
                float inheritanceCost = 2.0f * (combinedArea - area);

                // Cost of descending into child1
                float cost1;
                if (_nodes[child1].IsLeaf())
                {
                    AABB aabb = new AABB();
                    aabb.Combine(ref leafAABB, ref _nodes[child1].AABB);
                    cost1 = aabb.Perimeter + inheritanceCost;
                }
                else
                {
                    AABB aabb = new AABB();
                    aabb.Combine(ref leafAABB, ref _nodes[child1].AABB);
                    float oldArea = _nodes[child1].AABB.Perimeter;
                    float newArea = aabb.Perimeter;
                    cost1 = (newArea - oldArea) + inheritanceCost;
                }

                // Cost of descending into child2
                float cost2;
                if (_nodes[child2].IsLeaf())
                {
                    AABB aabb = new AABB();
                    aabb.Combine(ref leafAABB, ref _nodes[child2].AABB);
                    cost2 = aabb.Perimeter + inheritanceCost;
                }
                else
                {
                    AABB aabb = new AABB();
                    aabb.Combine(ref leafAABB, ref _nodes[child2].AABB);
                    float oldArea = _nodes[child2].AABB.Perimeter;
                    float newArea = aabb.Perimeter;
                    cost2 = newArea - oldArea + inheritanceCost;
                }

                // Descend according to the minimum cost.
                if (cost < cost1 && cost1 < cost2)
                {
                    break;
                }

                // Descend
                if (cost1 < cost2)
                {
                    index = child1;
                }
                else
                {
                    index = child2;
                }
            }

            int sibling = index;

            // Create a new parent.
            int oldParent = _nodes[sibling].ParentOrNext;
            int newParent = AllocateNode();

            _nodes[newParent].ParentOrNext = oldParent;
            _nodes[newParent].UserData     = default(T);
            _nodes[newParent].AABB.Combine(ref leafAABB, ref _nodes[sibling].AABB);
            _nodes[newParent].Height = _nodes[sibling].Height + 1;

            if (oldParent != NullNode)
            {
                // The sibling was not the root.
                if (_nodes[oldParent].Child1 == sibling)
                {
                    _nodes[oldParent].Child1 = newParent;
                }
                else
                {
                    _nodes[oldParent].Child2 = newParent;
                }

                _nodes[newParent].Child1     = sibling;
                _nodes[newParent].Child2     = leaf;
                _nodes[sibling].ParentOrNext = newParent;
                _nodes[leaf].ParentOrNext    = newParent;
            }
            else
            {
                // The sibling was the root.
                _nodes[newParent].Child1     = sibling;
                _nodes[newParent].Child2     = leaf;
                _nodes[sibling].ParentOrNext = newParent;
                _nodes[leaf].ParentOrNext    = newParent;
                _root = newParent;
            }

            // Walk back up the tree fixing heights and AABBs
            index = _nodes[leaf].ParentOrNext;
            while (index != NullNode)
            {
                index = Balance(index);

                int child1 = _nodes[index].Child1;
                int child2 = _nodes[index].Child2;

                Debug.Assert(child1 != NullNode);
                Debug.Assert(child2 != NullNode);

                _nodes[index].Height = 1 + Math.Max(_nodes[child1].Height, _nodes[child2].Height);
                _nodes[index].AABB.Combine(ref _nodes[child1].AABB, ref _nodes[child2].AABB);

                index = _nodes[index].ParentOrNext;
            }

            //Validate();
        }
Пример #2
0
        /// <summary>
        /// Build an optimal tree. Very expensive. For testing.
        /// </summary>
        public void RebuildBottomUp()
        {
            int[] nodes = new int[_nodeCount];
            int   count = 0;

            // Build array of leaves. Free the rest.
            for (int i = 0; i < _nodeCapacity; ++i)
            {
                if (_nodes[i].Height < 0)
                {
                    // free node in pool
                    continue;
                }

                if (_nodes[i].IsLeaf())
                {
                    _nodes[i].ParentOrNext = NullNode;
                    nodes[count]           = i;
                    ++count;
                }
                else
                {
                    FreeNode(i);
                }
            }

            while (count > 1)
            {
                float minCost = Settings.MaxFloat;
                int   iMin = -1, jMin = -1;
                for (int i = 0; i < count; ++i)
                {
                    AABB AABBi = _nodes[nodes[i]].AABB;

                    for (int j = i + 1; j < count; ++j)
                    {
                        AABB AABBj = _nodes[nodes[j]].AABB;
                        AABB b     = new AABB();
                        b.Combine(ref AABBi, ref AABBj);
                        float cost = b.Perimeter;
                        if (cost < minCost)
                        {
                            iMin    = i;
                            jMin    = j;
                            minCost = cost;
                        }
                    }
                }

                int          index1 = nodes[iMin];
                int          index2 = nodes[jMin];
                TreeNode <T> child1 = _nodes[index1];
                TreeNode <T> child2 = _nodes[index2];

                int          parentIndex = AllocateNode();
                TreeNode <T> parent      = _nodes[parentIndex];
                parent.Child1 = index1;
                parent.Child2 = index2;
                parent.Height = 1 + Math.Max(child1.Height, child2.Height);
                parent.AABB.Combine(ref child1.AABB, ref child2.AABB);
                parent.ParentOrNext = NullNode;

                child1.ParentOrNext = parentIndex;
                child2.ParentOrNext = parentIndex;

                nodes[jMin] = nodes[count - 1];
                nodes[iMin] = parentIndex;
                --count;
            }

            _root = nodes[0];

            Validate();
        }
Пример #3
0
        public void     InsertLeaf(IDistanceFieldPrimitive _Primitive)
        {
            AABB PrimAABB = new AABB()
            {
                m_Min = _Primitive.Min,
                m_Max = _Primitive.Max
            };
            Node Leaf = new Node()
            {
                m_AABB      = PrimAABB,
                m_Primitive = _Primitive
            };

            m_Primitives.Add(_Primitive);

            if (m_Root == null)
            {                   // This is our new root
                m_Root = Leaf;
                return;
            }

            // Find the best Sibling for this node
            AABB LeafAABB = Leaf.m_AABB;
            Node Current  = m_Root;

            while (!Leaf.IsLeaf)
            {
                Node Child0 = Leaf.Child0;
                Node Child1 = Leaf.Child1;

                float Area = Current.m_AABB.Perimeter;

                AABB CombinedAABB = Current.m_AABB;
                CombinedAABB.Combine(LeafAABB);
                float CombinedArea = CombinedAABB.Perimeter;

                // Cost of creating a new parent for this node and the new Leaf
                float Cost = 2.0f * CombinedArea;

                // Minimum Cost of pushing the Leaf further down the tree
                float InheritanceCost = 2.0f * (CombinedArea - Area);

                // Cost of descending into Child0
                AABB aabb = LeafAABB;
                aabb.Combine(Child0.m_AABB);
                float Cost0;
                if (Child0.IsLeaf)
                {
                    Cost0 = aabb.Perimeter + InheritanceCost;
                }
                else
                {
                    float OldArea = Child0.m_AABB.Perimeter;
                    float NewArea = aabb.Perimeter;
                    Cost0 = (NewArea - OldArea) + InheritanceCost;
                }

                // Cost of descending into Child1
                aabb = LeafAABB;
                aabb.Combine(Child1.m_AABB);
                float Cost1;
                if (Child1.IsLeaf)
                {
                    Cost1 = aabb.Perimeter + InheritanceCost;
                }
                else
                {
                    float OldArea = Child1.m_AABB.Perimeter;
                    float NewArea = aabb.Perimeter;
                    Cost1 = NewArea - OldArea + InheritanceCost;
                }

                // Descend according to the minimum Cost.
                if (Cost < Cost0 && Cost < Cost1)
                {
                    break;
                }


                // Descend
                if (Cost0 < Cost1)
                {
                    Current = Child0;
                }
                else
                {
                    Current = Child1;
                }
            }

            Node Sibling = Current;

            // Create a new parent.
            Node OldParent = Sibling.m_Parent;
            Node NewParent = new Node()
            {
                m_Parent = OldParent,
                m_Height = Sibling.m_Height + 1
            };

            NewParent.m_AABB = LeafAABB;
            NewParent.m_AABB.Combine(Sibling.m_AABB);
            if (OldParent != null)
            {                   // The Sibling was not the root.
                if (OldParent.Child0 == Sibling)
                {
                    OldParent.Child0 = NewParent;
                }
                else
                {
                    OldParent.Child1 = NewParent;
                }

                NewParent.Child0 = Sibling;
                NewParent.Child1 = Leaf;
                Sibling.m_Parent = NewParent;
                Leaf.m_Parent    = NewParent;
            }
            else
            {                   // The Sibling was the root.
                NewParent.Child0 = Sibling;
                NewParent.Child1 = Leaf;
                Sibling.m_Parent = NewParent;
                Leaf.m_Parent    = NewParent;
                m_Root           = NewParent;
            }

            // Walk back up the tree fixing heights and AABBs
            Current = Leaf.m_Parent;
            while (Current != null)
            {
                Current = Balance(Current);

                Node Child0 = Current.Child0;
                if (Child0 == null)
                {
                    throw new Exception("Unexpected null child!");
                }
                Node Child1 = Current.Child1;
                if (Child1 == null)
                {
                    throw new Exception("Unexpected null child!");
                }

                Current.m_Height = 1 + Math.Max(Child0.m_Height, Child1.m_Height);
                Current.m_AABB   = Child0.m_AABB;
                Current.m_AABB.Combine(Child1.m_AABB);

                Current = Current.m_Parent;
            }
        }
Пример #4
0
        private void InsertLeaf(int leaf)
        {
            ++_insertionCount;

            if (_root == NullNode)
            {
                _root = leaf;
                _nodes[_root].ParentOrNext = NullNode;
                return;
            }

            // Find the best sibling for this node
            AABB leafAABB = _nodes[leaf].AABB;
            int  sibling  = _root;

            while (_nodes[sibling].IsLeaf() == false)
            {
                int child1 = _nodes[sibling].Child1;
                int child2 = _nodes[sibling].Child2;

                // Expand the node's AABB.
                _nodes[sibling].AABB.Combine(ref leafAABB);
                _nodes[sibling].LeafCount += 1;

                float siblingArea = _nodes[sibling].AABB.Perimeter;
                AABB  parentAABB  = new AABB();
                parentAABB.Combine(ref _nodes[sibling].AABB, ref leafAABB);
                float parentArea = parentAABB.Perimeter;
                float cost1      = 2.0f * parentArea;

                float inheritanceCost = 2.0f * (parentArea - siblingArea);

                float cost2;
                if (_nodes[child1].IsLeaf())
                {
                    AABB aabb = new AABB();
                    aabb.Combine(ref leafAABB, ref _nodes[child1].AABB);
                    cost2 = aabb.Perimeter + inheritanceCost;
                }
                else
                {
                    AABB aabb = new AABB();
                    aabb.Combine(ref leafAABB, ref _nodes[child1].AABB);
                    float oldArea = _nodes[child1].AABB.Perimeter;
                    float newArea = aabb.Perimeter;
                    cost2 = (newArea - oldArea) + inheritanceCost;
                }

                float cost3;
                if (_nodes[child2].IsLeaf())
                {
                    AABB aabb = new AABB();
                    aabb.Combine(ref leafAABB, ref _nodes[child2].AABB);
                    cost3 = aabb.Perimeter + inheritanceCost;
                }
                else
                {
                    AABB aabb = new AABB();
                    aabb.Combine(ref leafAABB, ref _nodes[child2].AABB);
                    float oldArea = _nodes[child2].AABB.Perimeter;
                    float newArea = aabb.Perimeter;
                    cost3 = newArea - oldArea + inheritanceCost;
                }

                // Descend according to the minimum cost.
                if (cost1 < cost2 && cost1 < cost3)
                {
                    break;
                }

                // Expand the node's AABB to account for the new leaf.
                _nodes[sibling].AABB.Combine(ref leafAABB);

                // Descend
                if (cost2 < cost3)
                {
                    sibling = child1;
                }
                else
                {
                    sibling = child2;
                }
            }

            // Create a new parent for the siblings.
            int oldParent = _nodes[sibling].ParentOrNext;
            int newParent = AllocateNode();

            _nodes[newParent].ParentOrNext = oldParent;
            _nodes[newParent].UserData     = default(T);
            _nodes[newParent].AABB.Combine(ref leafAABB, ref _nodes[sibling].AABB);
            _nodes[newParent].LeafCount = _nodes[sibling].LeafCount + 1;

            if (oldParent != NullNode)
            {
                // The sibling was not the root.
                if (_nodes[oldParent].Child1 == sibling)
                {
                    _nodes[oldParent].Child1 = newParent;
                }
                else
                {
                    _nodes[oldParent].Child2 = newParent;
                }

                _nodes[newParent].Child1     = sibling;
                _nodes[newParent].Child2     = leaf;
                _nodes[sibling].ParentOrNext = newParent;
                _nodes[leaf].ParentOrNext    = newParent;
            }
            else
            {
                // The sibling was the root.
                _nodes[newParent].Child1     = sibling;
                _nodes[newParent].Child2     = leaf;
                _nodes[sibling].ParentOrNext = newParent;
                _nodes[leaf].ParentOrNext    = newParent;
                _root = newParent;
            }
        }
Пример #5
0
        /// <summary>
        /// Build an optimal tree. Very expensive. For testing.
        /// </summary>
        public void RebuildBottomUp()
        {
            var nodes = new int[m_nodeCount];
            int count = 0;

            // Build array of leaves. Free the rest.
            for (int i = 0; i < m_nodeCapacity; ++i)
            {
                if (m_nodes[i].Height < 0)
                {
                    // free node in pool
                    continue;
                }

                if (m_nodes[i].Leaf)
                {
                    m_nodes[i].Parent = TreeNode.NULL_NODE;
                    nodes[count] = i;
                    ++count;
                }
                else
                {
                    FreeNode(i);
                }
            }

            var b = new AABB();
            while (count > 1)
            {
                float minCost = Single.MaxValue;
                int iMin = -1, jMin = -1;
                for (int i = 0; i < count; ++i)
                {
                    AABB aabbi = m_nodes[nodes[i]].AABB;

                    for (int j = i + 1; j < count; ++j)
                    {
                        AABB aabbj = m_nodes[nodes[j]].AABB;
                        b.Combine(aabbi, aabbj);
                        float cost = b.Perimeter;
                        if (cost < minCost)
                        {
                            iMin = i;
                            jMin = j;
                            minCost = cost;
                        }
                    }
                }

                int index1 = nodes[iMin];
                int index2 = nodes[jMin];
                TreeNode child1 = m_nodes[index1];
                TreeNode child2 = m_nodes[index2];

                int parentIndex = AllocateNode();
                TreeNode parent = m_nodes[parentIndex];
                parent.Child1 = index1;
                parent.Child2 = index2;
                parent.Height = 1 + MathUtils.Max(child1.Height, child2.Height);
                parent.AABB.Combine(child1.AABB, child2.AABB);
                parent.Parent = TreeNode.NULL_NODE;

                child1.Parent = parentIndex;
                child2.Parent = parentIndex;

                nodes[jMin] = nodes[count - 1];
                nodes[iMin] = parentIndex;
                --count;
            }

            m_root = nodes[0];

            Validate();
        }
Пример #6
0
        private void ValidateMetrics(int index)
        {
            if (index == TreeNode.NULL_NODE)
            {
                return;
            }

            TreeNode node = m_nodes[index];

            int child1 = node.Child1;
            int child2 = node.Child2;

            if (node.Leaf)
            {
                Debug.Assert(child1 == TreeNode.NULL_NODE);
                Debug.Assert(child2 == TreeNode.NULL_NODE);
                Debug.Assert(node.Height == 0);
                return;
            }

            Debug.Assert(0 <= child1 && child1 < m_nodeCapacity);
            Debug.Assert(0 <= child2 && child2 < m_nodeCapacity);

            int height1 = m_nodes[child1].Height;
            int height2 = m_nodes[child2].Height;
            int height = 1 + MathUtils.Max(height1, height2);
            Debug.Assert(node.Height == height);

            var aabb = new AABB();
            aabb.Combine(m_nodes[child1].AABB, m_nodes[child2].AABB);

            Debug.Assert(aabb.LowerBound.Equals(node.AABB.LowerBound));
            Debug.Assert(aabb.UpperBound.Equals(node.AABB.UpperBound));

            ValidateMetrics(child1);
            ValidateMetrics(child2);
        }
Пример #7
0
 private void FillAabb()
 {
     shape.ComputeAABB(out aabb, transform, 0);
     shape.ComputeAABB(out _End, _EndTransform, 0);
     aabb.Combine(_End);
 }
Пример #8
0
        private void InsertLeaf(int leaf)
        {
            ++_insertionCount;

            if (_root == NullNode)
            {
                _root = leaf;
                _nodes[_root].ParentOrNext = NullNode;
                return;
            }

            // Find the best sibling for this node
            AABB leafAABB = _nodes[leaf].AABB;
            int  sibling  = _root;

            while (_nodes[sibling].IsLeaf() == false)
            {
                // Expand the node's AABB.
                _nodes[sibling].AABB.Combine(ref leafAABB);
                _nodes[sibling].LeafCount += 1;

                int child1 = _nodes[sibling].Child1;
                int child2 = _nodes[sibling].Child2;

#if false
                // This seems to create imbalanced trees
                Vector2 delta1 = Math.Abs(_nodes[child1].aabb.GetCenter() - leafCenter);
                Vector2 delta2 = Math.Abs(_nodes[child2].aabb.GetCenter() - leafCenter);

                float norm1 = delta1.x + delta1.y;
                float norm2 = delta2.x + delta2.y;
#else
                // Surface area heuristic
                AABB aabb1 = new AABB();
                AABB aabb2 = new AABB();
                aabb1.Combine(ref leafAABB, ref _nodes[child1].AABB);
                aabb2.Combine(ref leafAABB, ref _nodes[child2].AABB);
                float norm1 = (_nodes[child1].LeafCount + 1) * aabb1.Perimeter;
                float norm2 = (_nodes[child2].LeafCount + 1) * aabb2.Perimeter;
#endif

                if (norm1 < norm2)
                {
                    sibling = child1;
                }
                else
                {
                    sibling = child2;
                }
            }

            // Create a new parent for the siblings.
            int oldParent = _nodes[sibling].ParentOrNext;
            int newParent = AllocateNode();
            _nodes[newParent].ParentOrNext = oldParent;
            _nodes[newParent].UserData     = null;
            _nodes[newParent].AABB.Combine(ref leafAABB, ref _nodes[sibling].AABB);
            _nodes[newParent].LeafCount = _nodes[sibling].LeafCount + 1;

            if (oldParent != NullNode)
            {
                // The sibling was not the root.
                if (_nodes[oldParent].Child1 == sibling)
                {
                    _nodes[oldParent].Child1 = newParent;
                }
                else
                {
                    _nodes[oldParent].Child2 = newParent;
                }

                _nodes[newParent].Child1     = sibling;
                _nodes[newParent].Child2     = leaf;
                _nodes[sibling].ParentOrNext = newParent;
                _nodes[leaf].ParentOrNext    = newParent;
            }
            else
            {
                // The sibling was the root.
                _nodes[newParent].Child1     = sibling;
                _nodes[newParent].Child2     = leaf;
                _nodes[sibling].ParentOrNext = newParent;
                _nodes[leaf].ParentOrNext    = newParent;
                _root = newParent;
            }
        }
Пример #9
0
        private void InsertLeaf(int leaf)
        {
            InsertionCount++;

            if (m_root == TreeNode.NULL_NODE)
            {
                m_root = leaf;
                m_nodes[m_root].Parent = TreeNode.NULL_NODE;
                return;
            }

            // find the best sibling
            AABB leafAABB = m_nodes[leaf].AABB;
            int  index    = m_root;

            while (m_nodes[index].Leaf == false)
            {
                TreeNode node   = m_nodes[index];
                int      child1 = node.Child1;
                int      child2 = node.Child2;

                float area = node.AABB.Perimeter;

                combinedAABB.Combine(node.AABB, leafAABB);
                float combinedArea = combinedAABB.Perimeter;

                // Cost of creating a new parent for this node and the new leaf
                float cost = 2.0f * combinedArea;

                // Minimum cost of pushing the leaf further down the tree
                float inheritanceCost = 2.0f * (combinedArea - area);

                // Cost of descending into child1
                float cost1;
                if (m_nodes[child1].Leaf)
                {
                    combinedAABB.Combine(leafAABB, m_nodes[child1].AABB);
                    cost1 = combinedAABB.Perimeter + inheritanceCost;
                }
                else
                {
                    combinedAABB.Combine(leafAABB, m_nodes[child1].AABB);
                    float oldArea = m_nodes[child1].AABB.Perimeter;
                    float newArea = combinedAABB.Perimeter;
                    cost1 = (newArea - oldArea) + inheritanceCost;
                }

                // Cost of descending into child2
                float cost2;
                if (m_nodes[child2].Leaf)
                {
                    combinedAABB.Combine(leafAABB, m_nodes[child2].AABB);
                    cost2 = combinedAABB.Perimeter + inheritanceCost;
                }
                else
                {
                    combinedAABB.Combine(leafAABB, m_nodes[child2].AABB);
                    float oldArea = m_nodes[child2].AABB.Perimeter;
                    float newArea = combinedAABB.Perimeter;
                    cost2 = newArea - oldArea + inheritanceCost;
                }

                // Descend according to the minimum cost.
                if (cost < cost1 && cost < cost2)
                {
                    break;
                }

                // Descend
                index = cost1 < cost2 ? child1 : child2;
            }

            int      sibling     = index;
            int      oldParent   = m_nodes[sibling].Parent;
            int      newParentId = AllocateNode();
            TreeNode newParent   = m_nodes[newParentId];

            newParent.Parent   = oldParent;
            newParent.UserData = null;
            newParent.AABB.Combine(leafAABB, m_nodes[sibling].AABB);
            newParent.Height = m_nodes[sibling].Height + 1;

            if (oldParent != TreeNode.NULL_NODE)
            {
                // The sibling was not the root.
                if (m_nodes[oldParent].Child1 == sibling)
                {
                    m_nodes[oldParent].Child1 = newParentId;
                }
                else
                {
                    m_nodes[oldParent].Child2 = newParentId;
                }

                m_nodes[newParentId].Child1 = sibling;
                m_nodes[newParentId].Child2 = leaf;
                m_nodes[sibling].Parent     = newParentId;
                m_nodes[leaf].Parent        = newParentId;
            }
            else
            {
                // The sibling was the root.
                m_nodes[newParentId].Child1 = sibling;
                m_nodes[newParentId].Child2 = leaf;
                m_nodes[sibling].Parent     = newParentId;
                m_nodes[leaf].Parent        = newParentId;
                m_root = newParentId;
            }

            // Walk back up the tree fixing heights and AABBs
            index = m_nodes[leaf].Parent;
            while (index != TreeNode.NULL_NODE)
            {
                index = Balance(index);

                int child1 = m_nodes[index].Child1;
                int child2 = m_nodes[index].Child2;

                Debug.Assert(child1 != TreeNode.NULL_NODE);
                Debug.Assert(child2 != TreeNode.NULL_NODE);

                m_nodes[index].Height = 1 + MathUtils.Max(m_nodes[child1].Height, m_nodes[child2].Height);
                m_nodes[index].AABB.Combine(m_nodes[child1].AABB, m_nodes[child2].AABB);

                index = m_nodes[index].Parent;
            }

            // validate();
        }
Пример #10
0
        /// <summary>
        /// Build an optimal tree. Very expensive. For testing.
        /// </summary>
        public void RebuildBottomUp()
        {
            var nodes = new int[m_nodeCount];
            int count = 0;

            // Build array of leaves. Free the rest.
            for (int i = 0; i < m_nodeCapacity; ++i)
            {
                if (m_nodes[i].Height < 0)
                {
                    // free node in pool
                    continue;
                }

                if (m_nodes[i].Leaf)
                {
                    m_nodes[i].Parent = TreeNode.NULL_NODE;
                    nodes[count]      = i;
                    ++count;
                }
                else
                {
                    FreeNode(i);
                }
            }

            var b = new AABB();

            while (count > 1)
            {
                float minCost = Single.MaxValue;
                int   iMin = -1, jMin = -1;
                for (int i = 0; i < count; ++i)
                {
                    AABB aabbi = m_nodes[nodes[i]].AABB;

                    for (int j = i + 1; j < count; ++j)
                    {
                        AABB aabbj = m_nodes[nodes[j]].AABB;
                        b.Combine(aabbi, aabbj);
                        float cost = b.Perimeter;
                        if (cost < minCost)
                        {
                            iMin    = i;
                            jMin    = j;
                            minCost = cost;
                        }
                    }
                }

                int      index1 = nodes[iMin];
                int      index2 = nodes[jMin];
                TreeNode child1 = m_nodes[index1];
                TreeNode child2 = m_nodes[index2];

                int      parentIndex = AllocateNode();
                TreeNode parent      = m_nodes[parentIndex];
                parent.Child1 = index1;
                parent.Child2 = index2;
                parent.Height = 1 + MathUtils.Max(child1.Height, child2.Height);
                parent.AABB.Combine(child1.AABB, child2.AABB);
                parent.Parent = TreeNode.NULL_NODE;

                child1.Parent = parentIndex;
                child2.Parent = parentIndex;

                nodes[jMin] = nodes[count - 1];
                nodes[iMin] = parentIndex;
                --count;
            }

            m_root = nodes[0];

            Validate();
        }
Пример #11
0
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            CurrentFrameIndex++;
            DebugDrawCommands.Clear();

            float deltaSeconds = (float)gameTime.ElapsedGameTime.TotalSeconds;

            Perf.BeginSample(PerformanceSlots.InputUpdate);
            Input.Update(deltaSeconds);
            Perf.EndSample(PerformanceSlots.InputUpdate);

            if (Input.PlatformInput.WantsExit)
            {
                Exit();
            }

            if (Input.PlatformInput.ToggleFullscreen)
            {
                graphics.ToggleFullScreen();
            }

#if DEBUG
            deltaSeconds *= Input.DebugInput.SpeedMultiplier;

            {
                ActiveCamera.Movement.MovementVector = Input.DebugMovement;
            }

            if (Input.DebugInput.ToggleMainDrawing)
            {
                MainDrawingEnabled = !MainDrawingEnabled;
            }

            if (Input.DebugInput.ToggleDebugDrawing)
            {
                DebugDrawingEnabled = !DebugDrawingEnabled;
            }

            if (Input.DebugInput.TogglePhysicsDebugView)
            {
                PhysicsDebugView.Enabled = !PhysicsDebugView.Enabled;
            }

            if (Input.DebugInput.ToggleCameraVisibilityBounds)
            {
                if (ActiveCamera.CameraComponent.VisibilityBounds == null)
                {
                    ActiveCamera.CameraComponent.VisibilityBounds = CurrentLevel.LevelBounds;
                }
                else
                {
                    ActiveCamera.CameraComponent.VisibilityBounds = null;
                }

                if (ActiveCamera.SpringArm.Target == null)
                {
                    ActiveCamera.SpringArm.Target = Owliver;
                }
                else
                {
                    ActiveCamera.SpringArm.Target = null;
                }
            }

            if (Input.DebugInput.ResetCameraPosition)
            {
                ActiveCamera.Spatial.Position = Owliver.GetWorldSpatialData().Position;
            }
#endif

            {
                Owliver.Movement.MovementVector = Input.CharacterMovement;
                Owliver.Input = Input.CharacterInput;
            }

            // TODO(manu): Make use of `Input.CompationInput`!

            // Add pending game objects.
            GameObjects.AddRange(GameObjectsPendingAdd);
            foreach (GameObject go in GameObjectsPendingAdd)
            {
                go.Initialize();
                go.PostInitialize();
            }
            GameObjectsPendingAdd.Clear();

            // Execute pre-physics update.
            foreach (GameObject go in GameObjects)
            {
                go.PrePhysicsUpdate(deltaSeconds);
            }

            // Physics simulation
            float simTime = _excessSimTime + deltaSeconds;
            Perf.BeginSample(PerformanceSlots.WorldStep);
            while (simTime > _secondsPerSimStep)
            {
                World.Step(_secondsPerSimStep);
                simTime -= _secondsPerSimStep;
            }
            Perf.EndSample(PerformanceSlots.WorldStep);
            _excessSimTime = simTime;

            CurrentLevel.Update(deltaSeconds);

            // Post-physics update.
            foreach (GameObject go in GameObjects)
            {
                go.Update(deltaSeconds);

                AABB aabb = Global.CreateInvalidAABB();
                foreach (SpatialComponent sc in go.GetComponents <SpatialComponent>())
                {
                    AABB other = sc.GetWorldSpatialData().AbsoluteAABB;
                    aabb.Combine(ref other);
                }

                DebugDrawCommands.Add(view => view.DrawPoint(aabb.Center, Conversion.ToMeters(3), Color.MonoGameOrange));
                DebugDrawCommands.Add(view => view.DrawAABB(ref aabb, Color.Lime));
            }

            // Remove pending game objects.
            GameObjects.RemoveAll(go => GameObjectsPendingRemove.Contains(go));
            foreach (GameObject go in GameObjectsPendingRemove)
            {
                go.Destroy();
            }
            GameObjectsPendingRemove.Clear();

            base.Update(gameTime);

            Perf.AdvanceFrame();
        }