protected override void UpdateMultithreaded() { if (backbuffer.Count != entries.Count) { backbuffer.Capacity = entries.Capacity; backbuffer.Count = entries.Count; } Overlaps.Clear(); //Sort along x axis using insertion sort; the list will be nearly sorted, so very few swaps are necessary. for (int i = 1; i < entries.Count; i++) { var entry = entries.Elements[i]; for (int j = i - 1; j >= 0; j--) { if (entry.boundingBox.Min.X < entries.Elements[j].boundingBox.Min.X) { entries.Elements[j + 1] = entries.Elements[j]; entries.Elements[j] = entry; } else { break; } } } //TODO: Multithreaded sorting could help in some large cases. //The overhead involved in this implementation is way too high for reasonable object counts. //for (int i = 0; i < sortSegmentCount; i++) // SortSection(i); ////MergeSections(0, 1); ////MergeSections(2, 3); ////MergeSections(0, 2); ////MergeSections(1, 3); //MergeSections(0, 1); //MergeSections(2, 3); //MergeSections(4, 5); //MergeSections(6, 7); //MergeSections(0, 2); //MergeSections(1, 3); //MergeSections(4, 6); //MergeSections(5, 7); //MergeSections(0, 4); //MergeSections(1, 5); //MergeSections(2, 6); //MergeSections(3, 7); //var temp = backbuffer; //backbuffer = entries; //entries = temp; ParallelLooper.ForLoop(0, sweepSegmentCount, sweepSegment); }
protected override void UpdateSingleThreaded() { lock (Locker) { Overlaps.Clear(); //Update the placement of objects. for (int i = 0; i < entries.Count; i++) { //Compute the current cells occupied by the entry. var entry = entries.Elements[i]; Int2 min, max; ComputeCell(ref entry.item.boundingBox.Min, out min); ComputeCell(ref entry.item.boundingBox.Max, out max); //For any cell that used to be occupied (defined by the previous min/max), //remove the entry. for (int j = entry.previousMin.Y; j <= entry.previousMax.Y; j++) { for (int k = entry.previousMin.Z; k <= entry.previousMax.Z; k++) { if (j >= min.Y && j <= max.Y && k >= min.Z && k <= max.Z) { continue; //This cell is currently occupied, do not remove. } var index = new Int2 { Y = j, Z = k }; cellSet.Remove(ref index, entry); } } //For any cell that is newly occupied (was not previously contained), //add the entry. for (int j = min.Y; j <= max.Y; j++) { for (int k = min.Z; k <= max.Z; k++) { if (j >= entry.previousMin.Y && j <= entry.previousMax.Y && k >= entry.previousMin.Z && k <= entry.previousMax.Z) { continue; //This cell is already occupied, do not add. } var index = new Int2 { Y = j, Z = k }; cellSet.Add(ref index, entry); } } entry.previousMin = min; entry.previousMax = max; } //Update each cell to find the overlaps. for (int i = 0; i < cellSet.count; i++) { cellSet.cells.Elements[i].UpdateOverlaps(this); } } }
// Inherited public override void Clear() { Layering.Clear(); EventTriggers.Clear(); ExitTriggers.Clear(); NPCObjects.Clear(); Overlaps.Clear(); TileSwitches.Clear(); CollisionSwitches.Clear(); }
protected override void UpdateMultithreaded() { lock (Locker) { Overlaps.Clear(); //Update the entries! ParallelLooper.ForLoop(0, entries.Count, updateEntry); //Update the cells! ParallelLooper.ForLoop(0, cellSet.count, updateCell); } }
protected override void UpdateSingleThreaded() { Overlaps.Clear(); for (int i = 0; i < entries.Count; i++) { for (int j = i + 1; j < entries.Count; j++) { if (entries[i].boundingBox.Intersects(entries[j].boundingBox)) { base.TryToAddOverlap(entries[i], entries[j]); } } } }
protected override void UpdateSingleThreaded() { lock (Locker) { Overlaps.Clear(); if (root != null) { root.Refit(); if (!root.IsLeaf) //If the root is a leaf, it's alone- nothing to collide against! This test is required by the assumptions of the leaf-leaf test. { root.GetOverlaps(root, this); } } } }
/// <summary> /// Calculate a list of which views overlap this handle. /// </summary> /// <param name="group">The parent texture group, used to find a view's base CPU VA offset</param> /// <param name="views">The list of views to search for overlaps</param> public void RecalculateOverlaps(TextureGroup group, List <Texture> views) { // Overlaps can be accessed from the memory tracking signal handler, so access must be atomic. lock (Overlaps) { int endOffset = Offset + Size; Overlaps.Clear(); foreach (Texture view in views) { int viewOffset = group.FindOffset(view); if (viewOffset < endOffset && Offset < viewOffset + (int)view.Size) { Overlaps.Add(view); } } } }
protected override void UpdateSingleThreaded() { lock (Locker) { Overlaps.Clear(); if (root != null) { #if PROFILE startRefit = Stopwatch.GetTimestamp(); #endif SingleThreadedRefitPhase(); #if PROFILE endRefit = Stopwatch.GetTimestamp(); #endif SingleThreadedOverlapPhase(); #if PROFILE endOverlap = Stopwatch.GetTimestamp(); #endif } } }
protected override void UpdateMultithreaded() { lock (Locker) { Overlaps.Clear(); if (root != null) { int splitDepth = GetSplitDepth(); #if PROFILE startRefit = Stopwatch.GetTimestamp(); #endif MultithreadedRefitPhase(splitDepth); #if PROFILE endRefit = Stopwatch.GetTimestamp(); #endif MultithreadedOverlapPhase(splitDepth); #if PROFILE endOverlap = Stopwatch.GetTimestamp(); #endif } } }
protected override void UpdateSingleThreaded() { Overlaps.Clear(); //Sort along x axis using insertion sort; the list will be nearly sorted, so very few swaps are necessary. for (int i = 1; i < entries.Count; i++) { BroadPhaseEntry entry = entries.Elements[i]; for (int j = i - 1; j >= 0; j--) { if (entry.boundingBox.Min.X < entries.Elements[j].boundingBox.Min.X) { entries.Elements[j + 1] = entries.Elements[j]; entries.Elements[j] = entry; } else { break; } } } //Sweep the list looking for overlaps. for (int i = 0; i < entries.Count; i++) { BoundingBox a = entries.Elements[i].boundingBox; for (int j = i + 1; j < entries.Count && a.Max.X >= entries.Elements[j].boundingBox.Min.X; j++) { if (!(a.Min.Y > entries.Elements[j].boundingBox.Max.Y || a.Max.Y <entries.Elements[j].boundingBox.Min.Y || a.Min.Z> entries.Elements[j].boundingBox.Max.Z || a.Max.Z < entries.Elements[j].boundingBox.Min.Z)) { TryToAddOverlap(entries.Elements[i], entries.Elements[j]); } } } }
protected override void UpdateSingleThreaded() { overlapCandidatesX.Clear(); overlapCandidatesY.Clear(); Overlaps.Clear(); //Sort along x axis using insertion sort; the list will be nearly sorted, so very few swaps are necessary. for (int i = 1; i < entriesX.count; i++) { var entry = entriesX.Elements[i]; for (int j = i - 1; j >= 0; j--) { if (entry.boundingBox.Min.X < entriesX.Elements[j].boundingBox.Min.X) { entriesX.Elements[j + 1] = entriesX.Elements[j]; entriesX.Elements[j] = entry; } else { break; } } } //Sort along y axis using insertion sort; the list will be nearly sorted, so very few swaps are necessary. for (int i = 1; i < entriesY.count; i++) { var entry = entriesY.Elements[i]; for (int j = i - 1; j >= 0; j--) { if (entry.boundingBox.Min.Y < entriesY.Elements[j].boundingBox.Min.Y) { entriesY.Elements[j + 1] = entriesY.Elements[j]; entriesY.Elements[j] = entry; } else { break; } } } //Sort along z axis using insertion sort; the list will be nearly sorted, so very few swaps are necessary. for (int i = 1; i < entriesZ.count; i++) { var entry = entriesZ.Elements[i]; for (int j = i - 1; j >= 0; j--) { if (entry.boundingBox.Min.Z < entriesZ.Elements[j].boundingBox.Min.Z) { entriesZ.Elements[j + 1] = entriesZ.Elements[j]; entriesZ.Elements[j] = entry; } else { break; } } } //Hash-set based sweeping is way too slow. 3D sap is really best suited to an incremental approach. //Sweep the list looking for overlaps. //Sweep the X axis first; in this phase, add overlaps to the hash set if they exist. for (int i = 0; i < entriesX.count; i++) { BoundingBox a = entriesX.Elements[i].boundingBox; for (int j = i + 1; j < entriesX.count && a.Max.X > entriesX.Elements[j].boundingBox.Min.X; j++) { overlapCandidatesX.Add(new BroadPhaseOverlap(entriesX.Elements[i], entriesX.Elements[j])); } } //Sweep the Y axis second; same thing for (int i = 0; i < entriesY.count; i++) { BoundingBox a = entriesY.Elements[i].boundingBox; for (int j = i + 1; j < entriesY.count && a.Max.Y > entriesY.Elements[j].boundingBox.Min.Y; j++) { overlapCandidatesY.Add(new BroadPhaseOverlap(entriesY.Elements[i], entriesY.Elements[j])); } } //Sweep the Z axis last for (int i = 0; i < entriesZ.count; i++) { BoundingBox a = entriesZ.Elements[i].boundingBox; for (int j = i + 1; j < entriesZ.count && a.Max.Z > entriesZ.Elements[j].boundingBox.Min.Z; j++) { var overlap = new BroadPhaseOverlap(entriesZ.Elements[i], entriesZ.Elements[j]); if (overlapCandidatesX.Contains(overlap) && overlapCandidatesY.Contains(overlap)) { TryToAddOverlap(entriesZ.Elements[i], entriesZ.Elements[j]); } } } }