Exemplo n.º 1
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;
            }
        }
Exemplo n.º 2
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;
            }
        }