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)); } }
public void RemoveObject(Actor o) { for (ActorNode node = GetNodeForActor(o); node != null; node = GetNodeForActor(o)) { BSPCollisionNode bspNode = node.GetBSPNode(); node.Remove(); this.CheckRemoveNode(bspNode); } }
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); } } }
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 !"); } }
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); } } }
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); }
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; }
public void Dispose() { if (node != null) { node = null; } if (next != null) { next.Dispose(); next = null; } if (prev != null) { prev.Dispose(); prev = null; } }
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); } }
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); } }
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); } }
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); } }
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; } } }
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); }
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); }
public void SetParent(BSPCollisionNode parent_0) { this.parent = parent_0; }
public int GetChildSide(BSPCollisionNode child) { return((this.left == child) ? 0 : 1); }
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); } } } } }
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); }
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); } }