예제 #1
0
        // Can only remove overlapping pairs.
        // Sort edge down and remove pairs that are not overlapping anymore.
        // Needs to called after SortMinEdgeDown.
        private void SortMaxEdgeDown(List <Edge> edgeList, int axisIndex, int edgeIndex)
        {
            var edge     = edgeList[edgeIndex];
            var itemInfo = edge.Info;

            int previousEdgeIndex = edgeIndex - 1;
            var previousEdge      = edgeList[previousEdgeIndex];

            while (edge.Position < previousEdge.Position)
            {
                var previousItemInfo = previousEdge.Info;

                if (previousEdge.IsMax == false)
                {
                    // Remove overlapping pair.
                    var overlap = new Pair <T>(itemInfo.Item, previousItemInfo.Item);
                    if (_broadPhase != null)
                    {
                        _broadPhase.Remove(overlap);
                    }

                    if (EnableSelfOverlaps)
                    {
                        SelfOverlaps.Remove(overlap);
                    }

                    previousItemInfo.MinEdgeIndices[axisIndex] = edgeIndex; // Min edge was swapped up.
                }
                else
                {
                    previousItemInfo.MaxEdgeIndices[axisIndex] = edgeIndex; // Max edge was swapped up.
                }

                itemInfo.MaxEdgeIndices[axisIndex] = previousEdgeIndex; // Max edge was swapped down.

                // Swap edges in edge list.
                edgeList[edgeIndex]         = previousEdge;
                edgeList[previousEdgeIndex] = edge;

                edgeIndex--;
                previousEdgeIndex--;
                previousEdge = edgeList[previousEdgeIndex];
            }
        }
예제 #2
0
        // Can only remove overlapping pairs.
        // Sort edge up and remove pairs that are not overlapping anymore.
        // Needs to be called after SortMaxEdgeUp.
        private void SortMinEdgeUp(List <Edge> edgeList, int axisIndex, int edgeIndex)
        {
            var edge     = edgeList[edgeIndex];
            var itemInfo = edge.Info;

            int nextEdgeIndex = edgeIndex + 1;
            var nextEdge      = edgeList[nextEdgeIndex];

            while (edge.Position > nextEdge.Position)
            {
                var nextItemInfo = nextEdge.Info;

                if (nextEdge.IsMax)
                {
                    // Remove overlapping pair.
                    var overlap = new Pair <T>(itemInfo.Item, nextItemInfo.Item);
                    if (_broadPhase != null)
                    {
                        _broadPhase.Remove(overlap);
                    }

                    if (EnableSelfOverlaps)
                    {
                        SelfOverlaps.Remove(overlap);
                    }

                    nextItemInfo.MaxEdgeIndices[axisIndex] = edgeIndex; // Max edge was swapped down.
                }
                else
                {
                    nextItemInfo.MinEdgeIndices[axisIndex] = edgeIndex; // Min edge was swapped down.
                }

                itemInfo.MinEdgeIndices[axisIndex] = nextEdgeIndex; // Min edge was swapped up.

                // Swap edges in edge list.
                edgeList[edgeIndex]     = nextEdge;
                edgeList[nextEdgeIndex] = edge;

                edgeIndex++;
                nextEdgeIndex++;
                nextEdge = edgeList[nextEdgeIndex];
            }
        }
예제 #3
0
        private void UpdateSelfOverlaps(HashSet <T> addedItems, HashSet <T> removedItems, HashSet <T> invalidItems, List <Node> invalidNodes)
        {
            if (!EnableSelfOverlaps)
            {
                return;
            }

            // If the entire partition or a substantial amount of nodes is invalid use a tree vs. tree
            // checks. (Faster than leaf vs. tree checks. However, we need to determine the exact
            // threshold at which tree vs. tree is cheaper. The current threshold of Count / 2 is just
            // a guess.)
            if (invalidItems == null || addedItems.Count + invalidItems.Count > Count / 2)
            {
                // Recompute all self-overlaps by making a tree vs. tree test.
                SelfOverlaps.Clear();

                if (_root != null)
                {
                    // Important: Do not call GetOverlaps(this) because this would lead to recursive
                    // Update() calls!
                    // Note: Filtering is applied in GetOverlapsImpl(this).
                    foreach (var overlap in GetOverlapsImpl(this))
                    {
                        SelfOverlaps.Add(overlap);
                    }
                }
            }
            else
            {
                // Merge invalid and removed items into single set.
                // Store result in invalidItems.
                if (invalidItems.Count > 0 && removedItems.Count > 0)
                {
                    // Merge smaller set into larger set.
                    if (invalidItems.Count < removedItems.Count)
                    {
                        MathHelper.Swap(ref invalidItems, ref removedItems);
                    }

                    foreach (var item in removedItems)
                    {
                        invalidItems.Add(item);
                    }
                }
                else if (removedItems.Count > 0)
                {
                    invalidItems = removedItems;
                }

                // Remove invalid entries from self-overlaps.
                if (invalidItems.Count > 0)
                {
                    var invalidOverlaps = DigitalRune.ResourcePools <Pair <T> > .Lists.Obtain();

                    foreach (var overlap in SelfOverlaps)
                    {
                        if (invalidItems.Contains(overlap.First) || invalidItems.Contains(overlap.Second))
                        {
                            invalidOverlaps.Add(overlap);
                        }
                    }

                    foreach (var overlap in invalidOverlaps)
                    {
                        SelfOverlaps.Remove(overlap);
                    }

                    DigitalRune.ResourcePools <Pair <T> > .Lists.Recycle(invalidOverlaps);
                }

                // Compute new overlaps for all nodes that were updated in this frame.
                if (invalidNodes != null)
                {
                    foreach (var node in invalidNodes)
                    {
                        foreach (var touchedItem in GetOverlapsImpl(node))
                        {
                            var overlap = new Pair <T>(node.Item, touchedItem);
                            if (Filter == null || Filter.Filter(overlap))
                            {
                                SelfOverlaps.Add(overlap);
                            }
                        }
                    }
                }
            }
        }