Пример #1
0
        public Actor GetOnlyIntersectingObject(Actor actor, Type cls)
        {
            RectBox rect = this.GetActorBounds(actor);

            lock (this.actorQuery)
            {
                this.actorQuery.Init(cls, actor);
                ActorNode node = GetNodeForActor(actor);
                if (node == null)
                {
                    return(null);
                }
                do
                {
                    BSPCollisionNode bspNode = node.GetBSPNode();
                    Actor            result  = this.GetOnlyObjectDownTree(actor, rect,
                                                                          this.actorQuery, bspNode);
                    if (result != null)
                    {
                        return(result);
                    }
                    result = this.GetOnlyIntersectingUp(rect, this.actorQuery,
                                                        actor, bspNode.GetParent());
                    if (result != null)
                    {
                        return(result);
                    }
                    node = node.GetNext();
                } while (node != null);
                return(this.GetOnlyIntersectingDown(rect, this.actorQuery, actor));
            }
        }
Пример #2
0
 public void RemoveObject(Actor o)
 {
     for (ActorNode node = GetNodeForActor(o); node != null; node = GetNodeForActor(o))
     {
         BSPCollisionNode bspNode = node.GetBSPNode();
         node.Remove();
         this.CheckRemoveNode(bspNode);
     }
 }
Пример #3
0
 private void GetIntersectingObjects(float[] r,
                                     CollisionQuery query, ISet resultSet, BSPCollisionNode startNode)
 {
     lock (cacheNodeStack)
     {
         cacheNodeStack.Clear();
         try
         {
             if (startNode != null)
             {
                 CollectionUtils.Add(cacheNodeStack, startNode);
             }
             int idx = 0;
             for (; !(cacheNodeStack.Count == 0) && idx < MAX_SIZE;)
             {
                 BSPCollisionNode node = (BSPCollisionNode)cacheNodeStack
                                         .RemoveLast();
                 lock (node)
                 {
                     if (node.GetArea().Intersects(r[0], r[1], r[2], r[3]))
                     {
                         IIterator i = node.GetActorsIterator();
                         for (; i.HasNext();)
                         {
                             Actor left = (Actor)i.Next();
                             if (query.CheckCollision(left) &&
                                 !CollectionUtils.Contains(left, resultSet))
                             {
                                 CollectionUtils.Add(resultSet, left);
                             }
                         }
                         BSPCollisionNode left1 = node.GetLeft();
                         BSPCollisionNode right = node.GetRight();
                         if (left1 != null)
                         {
                             CollectionUtils.Add(cacheNodeStack, left1);
                         }
                         if (right != null)
                         {
                             CollectionUtils.Add(cacheNodeStack, right);
                         }
                     }
                 }
                 idx++;
             }
         }
         catch (Exception ex)
         {
             Loon.Utils.Debug.Log.Exception(ex);
         }
     }
 }
Пример #4
0
 private void ReturnNode(BSPCollisionNode node)
 {
     cache[tail++] = node;
     if (tail == MAX_SIZE)
     {
         tail = 0;
     }
     size = MathUtils.Min(size + 1, MAX_SIZE);
     if (node.GetLeft() != null || node.GetRight() != null)
     {
         throw new Exception("Size Error !");
     }
 }
Пример #5
0
 private void InsertObject(Actor actor, RectBox actorBounds, RectBox bounds,
                           RectBox area, BSPCollisionNode node, RectBox result1,
                           RectBox result2)
 {
     if (!node.ContainsActor(actor))
     {
         if (!node.IsEmpty() &&
             (area.width > actorBounds.width || area.height > actorBounds.height))
         {
             RectBox leftArea       = node.GetLeftArea();
             RectBox rightArea      = node.GetRightArea();
             RectBox leftIntersects = RectBox.GetIntersection(leftArea,
                                                              bounds, result1);
             RectBox rightIntersects = RectBox.GetIntersection(rightArea,
                                                               bounds, result2);
             BSPCollisionNode newRight;
             if (leftIntersects != null)
             {
                 if (node.GetLeft() == null)
                 {
                     newRight = this.CreateNewNode(leftArea);
                     newRight.AddActor(actor);
                     node.SetChild(0, newRight);
                 }
                 else
                 {
                     this.InsertObject(actor, actorBounds, leftIntersects,
                                       leftArea, node.GetLeft(), result1, result2);
                 }
             }
             if (rightIntersects != null)
             {
                 if (node.GetRight() == null)
                 {
                     newRight = this.CreateNewNode(rightArea);
                     newRight.AddActor(actor);
                     node.SetChild(1, newRight);
                 }
                 else
                 {
                     this.InsertObject(actor, actorBounds, rightIntersects,
                                       rightArea, node.GetRight(), result1, result2);
                 }
             }
         }
         else
         {
             node.AddActor(actor);
         }
     }
 }
Пример #6
0
 public Actor GetOnlyIntersectingUp(RectBox r,
                                    CollisionQuery query, Actor actor, BSPCollisionNode start)
 {
     for (; start != null && !start.GetArea().Contains(r);)
     {
         Actor res = this.CheckForOnlyCollision(actor, start, query);
         if (res != null)
         {
             return(res);
         }
         start = start.GetParent();
     }
     return(null);
 }
Пример #7
0
        public ActorNode(Actor actor, BSPCollisionNode node)
        {
            this.actor = actor;
            this.node  = node;
            ActorNode first = BSPCollisionChecker.GetNodeForActor(actor);

            this.next = first;
            BSPCollisionChecker.SetNodeForActor(actor, this);
            if (this.next != null)
            {
                this.next.prev = this;
            }

            this.mark = true;
        }
Пример #8
0
 public void Dispose()
 {
     if (node != null)
     {
         node = null;
     }
     if (next != null)
     {
         next.Dispose();
         next = null;
     }
     if (prev != null)
     {
         prev.Dispose();
         prev = null;
     }
 }
Пример #9
0
 public virtual IList GetObjects(Type cls)
 {
     lock (cacheSet)
     {
         CollectionUtils.Clear(cacheSet);
     }
     lock (cacheNodeStack)
     {
         if (this.bspTree != null)
         {
             CollectionUtils.Add(cacheNodeStack, this.bspTree);
         }
         for (; !(cacheNodeStack.Count == 0);)
         {
             BSPCollisionNode node = (BSPCollisionNode)cacheNodeStack
                                     .RemoveLast();
             IIterator i = node.GetActorsIterator();
             while (i.HasNext())
             {
                 Actor left = (Actor)i.Next();
                 if (cls == null || cls.IsInstanceOfType(left))
                 {
                     CollectionUtils.Add(cacheSet, left);
                 }
             }
             BSPCollisionNode left1 = node.GetLeft();
             BSPCollisionNode right = node.GetRight();
             if (left1 != null)
             {
                 CollectionUtils.Add(cacheNodeStack, left1);
             }
             if (right != null)
             {
                 CollectionUtils.Add(cacheNodeStack, right);
             }
         }
         List <Actor> result = new List <Actor>(cacheSet.Count);
         for (IEnumerator it = cacheSet.GetEnumerator(); it.MoveNext();)
         {
             result.Add((Actor)it.Current);
         }
         return(result);
     }
 }
Пример #10
0
 private Actor GetOnlyObjectDownTree(Actor ignore, RectBox r,
                                     CollisionQuery query, BSPCollisionNode startNode)
 {
     if (startNode == null)
     {
         return(null);
     }
     else
     {
         lock (cacheNodeStack)
         {
             cacheNodeStack.Clear();
             if (startNode != null)
             {
                 CollectionUtils.Add(cacheNodeStack, startNode);
             }
             while (!(cacheNodeStack.Count == 0))
             {
                 BSPCollisionNode node = (BSPCollisionNode)cacheNodeStack
                                         .RemoveLast();
                 if (node.GetArea().Intersects(r))
                 {
                     Actor res = this.CheckForOnlyCollision(ignore, node,
                                                            query);
                     if (res != null)
                     {
                         return(res);
                     }
                     BSPCollisionNode left  = node.GetLeft();
                     BSPCollisionNode right = node.GetRight();
                     if (left != null)
                     {
                         CollectionUtils.Add(cacheNodeStack, left);
                     }
                     if (right != null)
                     {
                         CollectionUtils.Add(cacheNodeStack, right);
                     }
                 }
             }
         }
         return(null);
     }
 }
Пример #11
0
 private BSPCollisionNode GetBSPNode()
 {
     if (size == 0)
     {
         return(new BSPCollisionNode(new RectBox(), 0, 0));
     }
     else
     {
         int ppos = tail - size;
         if (ppos < 0)
         {
             ppos += MAX_SIZE;
         }
         BSPCollisionNode node = cache[ppos];
         node.SetParent((BSPCollisionNode)null);
         --size;
         return(node);
     }
 }
Пример #12
0
        private Actor GetOnlyIntersectingDown(RectBox r,
                                              CollisionQuery query, Actor actor)
        {
            if (this.bspTree == null)
            {
                return(null);
            }
            else
            {
                lock (cacheNodeStack)
                {
                    cacheNodeStack.Clear();
                    CollectionUtils.Add(cacheNodeStack, this.bspTree);
                    int idx = 0;
                    for (; !(cacheNodeStack.Count == 0) && idx < MAX_SIZE;)
                    {
                        BSPCollisionNode node = (BSPCollisionNode)cacheNodeStack
                                                .RemoveLast();
                        if (node.GetArea().Contains(r))
                        {
                            Actor res = this.CheckForOnlyCollision(actor, node,
                                                                   query);
                            if (res != null)
                            {
                                return(res);
                            }

                            BSPCollisionNode left  = node.GetLeft();
                            BSPCollisionNode right = node.GetRight();
                            if (left != null)
                            {
                                CollectionUtils.Add(cacheNodeStack, left);
                            }
                            if (right != null)
                            {
                                CollectionUtils.Add(cacheNodeStack, right);
                            }
                        }
                    }
                }
                return(null);
            }
        }
Пример #13
0
 public void SetChild(int side, BSPCollisionNode child)
 {
     if (side == 0)
     {
         this.left = child;
         if (child != null)
         {
             child.parent = this;
         }
     }
     else
     {
         this.right = child;
         if (child != null)
         {
             child.parent = this;
         }
     }
 }
Пример #14
0
        private Actor CheckForOnlyCollision(Actor ignore,
                                            BSPCollisionNode node, CollisionQuery query)
        {
            if (node == null)
            {
                return(null);
            }
            IIterator i = node.GetActorsIterator();
            Actor     candidate;

            do
            {
                if (!i.HasNext())
                {
                    return(null);
                }
                candidate = (Actor)i.Next();
            } while (ignore == candidate || !query.CheckCollision(candidate));
            return(candidate);
        }
Пример #15
0
        private BSPCollisionNode CreateNewNode(RectBox area)
        {
            byte  splitAxis;
            float splitPos;

            if (area.width > area.height)
            {
                splitAxis = 0;
                splitPos  = area.GetMiddleX();
            }
            else
            {
                splitAxis = 1;
                splitPos  = area.GetMiddleY();
            }

            BSPCollisionNode newNode = GetBSPNode();

            newNode.SetArea(area);
            newNode.SetSplitAxis(splitAxis);
            newNode.SetSplitPos(splitPos);
            return(newNode);
        }
Пример #16
0
 public void SetParent(BSPCollisionNode parent_0)
 {
     this.parent = parent_0;
 }
Пример #17
0
 public int GetChildSide(BSPCollisionNode child)
 {
     return((this.left == child) ? 0 : 1);
 }
Пример #18
0
        private void UpdateObject(Actor o)
        {
            ActorNode node = GetNodeForActor(o);

            if (node != null)
            {
                RectBox          newBounds = this.GetActorBounds(o);
                BSPCollisionNode bspNode;
                if (!this.bspTree.GetArea().Contains(newBounds))
                {
                    for (; node != null;)
                    {
                        bspNode = node.GetBSPNode();
                        node.Remove();
                        this.CheckRemoveNode(bspNode);
                        node = node.GetNext();
                    }
                    this.AddObject(o);
                }
                else
                {
                    RectBox bspArea;
                    RectBox result1 = new RectBox();
                    RectBox result2 = new RectBox();
                    while (node != null)
                    {
                        bspNode = node.GetBSPNode();
                        bspArea = bspNode.GetArea();
                        if (bspArea.Contains(newBounds))
                        {
                            for (ActorNode rNode2 = GetNodeForActor(o); rNode2 != null; rNode2 = rNode2
                                                                                                 .GetNext())
                            {
                                if (rNode2 != node)
                                {
                                    BSPCollisionNode rNode1 = rNode2.GetBSPNode();
                                    rNode2.Remove();
                                    this.CheckRemoveNode(rNode1);
                                }
                            }
                            return;
                        }
                        if (!bspArea.Intersects(newBounds))
                        {
                            BSPCollisionNode rNode = node.GetBSPNode();
                            node.Remove();
                            this.CheckRemoveNode(rNode);
                        }
                        node.ClearMark();
                        node = node.GetNext();
                    }
                    node = GetNodeForActor(o);
                    if (node != null)
                    {
                        for (bspNode = node.GetBSPNode(); bspNode != null &&
                             !bspNode.GetArea().Contains(newBounds); bspNode = bspNode
                                                                               .GetParent())
                        {
                            ;
                        }
                        if (bspNode == null)
                        {
                            while (node != null)
                            {
                                bspNode = node.GetBSPNode();
                                node.Remove();
                                this.CheckRemoveNode(bspNode);
                                node = node.GetNext();
                            }

                            this.AddObject(o);
                            return;
                        }
                    }
                    else
                    {
                        bspNode = this.bspTree;
                    }

                    bspArea = bspNode.GetArea();
                    this.InsertObject(o, newBounds, newBounds, bspArea,
                                      bspNode, result1, result2);
                    for (node = GetNodeForActor(o); node != null; node = node
                                                                         .GetNext())
                    {
                        if (!node.CheckMark())
                        {
                            bspNode = node.GetBSPNode();
                            node.Remove();
                            this.CheckRemoveNode(bspNode);
                        }
                    }
                }
            }
        }
Пример #19
0
        private BSPCollisionNode CheckRemoveNode(BSPCollisionNode node)
        {
            int idx = 0;

            for (; idx < MAX_SIZE;)
            {
                if (node != null && node.IsEmpty())
                {
                    BSPCollisionNode parent = node.GetParent();
                    int side = (parent != null) ? parent.GetChildSide(node) : 3;
                    BSPCollisionNode left  = node.GetLeft();
                    BSPCollisionNode right = node.GetRight();
                    if (left == null)
                    {
                        if (parent != null)
                        {
                            if (right != null)
                            {
                                right.SetArea(node.GetArea());
                            }
                            parent.SetChild(side, right);
                        }
                        else
                        {
                            this.bspTree = right;
                            if (right != null)
                            {
                                right.SetParent((BSPCollisionNode)null);
                            }
                        }
                        node.SetChild(1, (BSPCollisionNode)null);
                        ReturnNode(node);
                        node = parent;
                        continue;
                    }

                    if (right == null)
                    {
                        if (parent != null)
                        {
                            if (left != null)
                            {
                                left.SetArea(node.GetArea());
                            }

                            parent.SetChild(side, left);
                        }
                        else
                        {
                            this.bspTree = left;
                            if (left != null)
                            {
                                left.SetParent((BSPCollisionNode)null);
                            }
                        }

                        node.SetChild(0, (BSPCollisionNode)null);
                        ReturnNode(node);
                        node = parent;
                        continue;
                    }
                }
                idx++;
                return(node);
            }
            return(null);
        }
Пример #20
0
        public void AddObject(Actor actor)
        {
            RectBox bounds = this.GetActorBounds(actor);
            float   by;

            if (this.bspTree == null)
            {
                byte treeArea;
                if (bounds.width > bounds.height)
                {
                    treeArea = 0;
                    by       = bounds.GetMiddleX();
                }
                else
                {
                    treeArea = 1;
                    by       = bounds.GetMiddleY();
                }

                this.bspTree = GetBSPNode();
                this.bspTree.GetArea().Copy(bounds);
                this.bspTree.SetSplitAxis(treeArea);
                this.bspTree.SetSplitPos(by);
                this.bspTree.AddActor(actor);
            }
            else
            {
                int     idx       = 0;
                RectBox treeArea1 = this.bspTree.GetArea();
                RectBox result1   = new RectBox();
                RectBox result2   = new RectBox();
                for (; !treeArea1.Contains(bounds) && idx < MAX_SIZE;)
                {
                    RectBox          newArea;
                    BSPCollisionNode newTop;
                    if (bounds.GetX() < treeArea1.GetX())
                    {
                        by      = (treeArea1.GetX() - treeArea1.width);
                        newArea = new RectBox(by, treeArea1.GetY(),
                                              treeArea1.GetRight() - by, treeArea1.height);
                        newTop = GetBSPNode();
                        newTop.GetArea().Copy(newArea);
                        newTop.SetSplitAxis(0);
                        newTop.SetSplitPos(treeArea1.GetX());
                        newTop.SetChild(1, this.bspTree);
                        this.bspTree = newTop;
                        treeArea1    = newArea;
                    }
                    if (bounds.GetRight() > treeArea1.GetRight())
                    {
                        by      = (treeArea1.GetRight() + treeArea1.width);
                        newArea = new RectBox(treeArea1.GetX(), treeArea1.GetY(),
                                              by - treeArea1.GetX(), treeArea1.height);
                        newTop = GetBSPNode();
                        newTop.GetArea().Copy(newArea);
                        newTop.SetSplitAxis(0);
                        newTop.SetSplitPos(treeArea1.GetRight());
                        newTop.SetChild(0, this.bspTree);
                        this.bspTree = newTop;
                        treeArea1    = newArea;
                    }
                    if (bounds.GetY() < treeArea1.GetY())
                    {
                        by      = (treeArea1.GetY() - treeArea1.height);
                        newArea = new RectBox(treeArea1.GetX(), by,
                                              treeArea1.width, treeArea1.GetBottom() - by);
                        newTop = GetBSPNode();
                        newTop.GetArea().Copy(newArea);
                        newTop.SetSplitAxis(1);
                        newTop.SetSplitPos(treeArea1.GetY());
                        newTop.SetChild(1, this.bspTree);
                        this.bspTree = newTop;
                        treeArea1    = newArea;
                    }
                    if (bounds.GetBottom() > treeArea1.GetBottom())
                    {
                        by      = (treeArea1.GetBottom() + treeArea1.height);
                        newArea = new RectBox(treeArea1.GetX(), treeArea1.GetY(),
                                              treeArea1.width, by - treeArea1.GetY());
                        newTop = GetBSPNode();
                        newTop.GetArea().Copy(newArea);
                        newTop.SetSplitAxis(1);
                        newTop.SetSplitPos(treeArea1.GetBottom());
                        newTop.SetChild(0, this.bspTree);
                        this.bspTree = newTop;
                        treeArea1    = newArea;
                    }
                    idx++;
                }

                this.InsertObject(actor, bounds, bounds, treeArea1, this.bspTree,
                                  result1, result2);
            }
        }