From d3d966cccce49c8e2155918390dc3dbd37278d81 Mon Sep 17 00:00:00 2001 From: ikpil Date: Thu, 4 May 2023 00:29:08 +0900 Subject: [PATCH] crowd performance --- src/DotRecast.Detour.Crowd/Crowd.cs | 8 +- src/DotRecast.Detour.Crowd/ProximityGrid.cs | 117 +++++++------------ src/DotRecast.Recast.Demo/Tools/CrowdTool.cs | 10 +- 3 files changed, 53 insertions(+), 82 deletions(-) diff --git a/src/DotRecast.Detour.Crowd/Crowd.cs b/src/DotRecast.Detour.Crowd/Crowd.cs index 1096b71..fb80256 100644 --- a/src/DotRecast.Detour.Crowd/Crowd.cs +++ b/src/DotRecast.Detour.Crowd/Crowd.cs @@ -869,7 +869,7 @@ namespace DotRecast.Detour.Crowd { Vector3f p = ag.npos; float r = ag.option.radius; - m_grid.addItem(ag, p.x - r, p.z - r, p.x + r, p.z + r); + m_grid.AddItem(ag, p.x - r, p.z - r, p.x + r, p.z + r); } _telemetry.stop("buildProximityGrid"); @@ -901,12 +901,12 @@ namespace DotRecast.Detour.Crowd _telemetry.stop("buildNeighbours"); } + private List getNeighbours(Vector3f pos, float height, float range, CrowdAgent skip, ProximityGrid grid) { List result = new List(); - HashSet proxAgents = grid.queryItems(pos.x - range, pos.z - range, pos.x + range, pos.z + range); - + HashSet proxAgents = grid.QueryItems(pos.x - range, pos.z - range, pos.x + range, pos.z + range); foreach (CrowdAgent ag in proxAgents) { if (ag == skip) @@ -1392,4 +1392,4 @@ namespace DotRecast.Detour.Crowd } }; } -} +} \ No newline at end of file diff --git a/src/DotRecast.Detour.Crowd/ProximityGrid.cs b/src/DotRecast.Detour.Crowd/ProximityGrid.cs index e2e1214..8a61875 100644 --- a/src/DotRecast.Detour.Crowd/ProximityGrid.cs +++ b/src/DotRecast.Detour.Crowd/ProximityGrid.cs @@ -20,44 +20,60 @@ freely, subject to the following restrictions: using System; using System.Collections.Generic; +using System.ComponentModel.Design; using System.Linq; namespace DotRecast.Detour.Crowd { public class ProximityGrid { - private readonly float m_cellSize; - private readonly float m_invCellSize; - private readonly Dictionary> items; + private readonly float _cellSize; + private readonly float _invCellSize; + private readonly Dictionary> _items; - public ProximityGrid(float m_cellSize) + public ProximityGrid(float cellSize) { - this.m_cellSize = m_cellSize; - m_invCellSize = 1.0f / m_cellSize; - items = new Dictionary>(); + _cellSize = cellSize; + _invCellSize = 1.0f / cellSize; + _items = new Dictionary>(); } - void clear() + public static long CombineKey(int x, int y) { - items.Clear(); + uint ux = (uint)x; + uint uy = (uint)y; + return ((long)ux << 32) | uy; } - public void addItem(CrowdAgent agent, float minx, float miny, float maxx, float maxy) + public static void DecomposeKey(long key, out int x, out int y) { - int iminx = (int)Math.Floor(minx * m_invCellSize); - int iminy = (int)Math.Floor(miny * m_invCellSize); - int imaxx = (int)Math.Floor(maxx * m_invCellSize); - int imaxy = (int)Math.Floor(maxy * m_invCellSize); + uint ux = (uint)(key >> 32); + uint uy = (uint)key; + x = (int)ux; + y = (int)uy; + } + + void Clear() + { + _items.Clear(); + } + + public void AddItem(CrowdAgent agent, float minx, float miny, float maxx, float maxy) + { + int iminx = (int)Math.Floor(minx * _invCellSize); + int iminy = (int)Math.Floor(miny * _invCellSize); + int imaxx = (int)Math.Floor(maxx * _invCellSize); + int imaxy = (int)Math.Floor(maxy * _invCellSize); for (int y = iminy; y <= imaxy; ++y) { for (int x = iminx; x <= imaxx; ++x) { - ItemKey key = new ItemKey(x, y); - if (!items.TryGetValue(key, out var ids)) + long key = CombineKey(x, y); + if (!_items.TryGetValue(key, out var ids)) { ids = new List(); - items.Add(key, ids); + _items.Add(key, ids); } ids.Add(agent); @@ -65,20 +81,20 @@ namespace DotRecast.Detour.Crowd } } - public HashSet queryItems(float minx, float miny, float maxx, float maxy) + public HashSet QueryItems(float minx, float miny, float maxx, float maxy) { - int iminx = (int)Math.Floor(minx * m_invCellSize); - int iminy = (int)Math.Floor(miny * m_invCellSize); - int imaxx = (int)Math.Floor(maxx * m_invCellSize); - int imaxy = (int)Math.Floor(maxy * m_invCellSize); + int iminx = (int)Math.Floor(minx * _invCellSize); + int iminy = (int)Math.Floor(miny * _invCellSize); + int imaxx = (int)Math.Floor(maxx * _invCellSize); + int imaxy = (int)Math.Floor(maxy * _invCellSize); HashSet result = new HashSet(); for (int y = iminy; y <= imaxy; ++y) { for (int x = iminx; x <= imaxx; ++x) { - ItemKey key = new ItemKey(x, y); - if (items.TryGetValue(key, out var ids)) + long key = CombineKey(x, y); + if (_items.TryGetValue(key, out var ids)) { result.UnionWith(ids); } @@ -88,59 +104,16 @@ namespace DotRecast.Detour.Crowd return result; } - public List getItemCounts() + public IEnumerable<(long, int)> GetItemCounts() { - return items + return _items .Where(e => e.Value.Count > 0) - .Select(e => new int[] { e.Key.x, e.Key.y, e.Value.Count }) - .ToList(); + .Select(e => (e.Key, e.Value.Count)); } - public float getCellSize() + public float GetCellSize() { - return m_cellSize; + return _cellSize; } - - private class ItemKey - { - public readonly int x; - public readonly int y; - - public ItemKey(int x, int y) - { - this.x = x; - this.y = y; - } - - public override int GetHashCode() - { - int prime = 31; - int result = 1; - result = prime * result + x; - result = prime * result + y; - return result; - } - - public override bool Equals(object? obj) - { - if (this == obj) - return true; - - if (obj == null) - return false; - - if (GetType() != obj.GetType()) - return false; - - ItemKey other = (ItemKey)obj; - if (x != other.x) - return false; - - if (y != other.y) - return false; - - return true; - } - }; } } \ No newline at end of file diff --git a/src/DotRecast.Recast.Demo/Tools/CrowdTool.cs b/src/DotRecast.Recast.Demo/Tools/CrowdTool.cs index 2bbebd9..4aa0ea1 100644 --- a/src/DotRecast.Recast.Demo/Tools/CrowdTool.cs +++ b/src/DotRecast.Recast.Demo/Tools/CrowdTool.cs @@ -408,12 +408,10 @@ public class CrowdTool : Tool dd.begin(QUADS); ProximityGrid grid = crowd.getGrid(); - float cs = grid.getCellSize(); - foreach (int[] ic in grid.getItemCounts()) + float cs = grid.GetCellSize(); + foreach (var (combinedKey, count) in grid.GetItemCounts()) { - int x = ic[0]; - int y = ic[1]; - int count = ic[2]; + ProximityGrid.DecomposeKey(combinedKey, out var x, out var y); if (count != 0) { int col = duRGBA(128, 0, 0, Math.Min(count * 40, 255)); @@ -838,4 +836,4 @@ public class CrowdTool : Tool { return "Crowd"; } -} +} \ No newline at end of file