separated Crowd, Crowd profiling

This commit is contained in:
ikpil 2023-09-09 12:42:30 +09:00
parent 56fb2cd8a9
commit be1dad863f
11 changed files with 178 additions and 83 deletions

View File

@ -386,7 +386,8 @@ public class RecastDemo : IRecastDemoChannel
new ObstacleSampleTool(), new ObstacleSampleTool(),
new OffMeshConnectionSampleTool(), new OffMeshConnectionSampleTool(),
new ConvexVolumeSampleTool(), new ConvexVolumeSampleTool(),
new CrowdSampleTool(), new CrowdampleTool(),
new CrowdProfilingSampleTool(),
new JumpLinkBuilderSampleTool(), new JumpLinkBuilderSampleTool(),
new DynamicUpdateSampleTool() new DynamicUpdateSampleTool()
); );

View File

@ -28,13 +28,21 @@ using DotRecast.Recast.Demo.Draw;
using DotRecast.Recast.Toolset; using DotRecast.Recast.Toolset;
using DotRecast.Recast.Toolset.Tools; using DotRecast.Recast.Toolset.Tools;
using ImGuiNET; using ImGuiNET;
using Serilog;
using static DotRecast.Recast.Demo.Draw.DebugDraw; using static DotRecast.Recast.Demo.Draw.DebugDraw;
namespace DotRecast.Recast.Demo.Tools; namespace DotRecast.Recast.Demo.Tools;
public class CrowdProfilingTool public class CrowdProfilingSampleTool : ISampleTool
{ {
private readonly Func<DtCrowdAgentParams> agentParamsSupplier; private static readonly ILogger Logger = Log.ForContext<CrowdProfilingSampleTool>();
private DemoSample _sample;
private DtNavMesh m_nav;
private readonly CrowdToolParams toolParams = new CrowdToolParams();
private RcCrowdProfilingTool _tool;
private int expandSimOptions = 1; private int expandSimOptions = 1;
private int expandCrowdOptions = 1; private int expandCrowdOptions = 1;
private int agents = 1000; private int agents = 1000;
@ -52,13 +60,113 @@ public class CrowdProfilingTool
private readonly List<DtPolyPoint> _polyPoints = new(); private readonly List<DtPolyPoint> _polyPoints = new();
private long crowdUpdateTime; private long crowdUpdateTime;
public CrowdProfilingTool(Func<DtCrowdAgentParams> agentParamsSupplier) public CrowdProfilingSampleTool()
{ {
this.agentParamsSupplier = agentParamsSupplier; _tool = new();
}
public void SetSample(DemoSample sample)
{
_sample = sample;
}
public void OnSampleChanged()
{
var geom = _sample.GetInputGeom();
var settings = _sample.GetSettings();
var navMesh = _sample.GetNavMesh();
if (navMesh != null && m_nav != navMesh)
{
m_nav = navMesh;
Setup(settings.agentRadius, m_nav);
}
}
private DtCrowdAgentParams GetAgentParams()
{
var settings = _sample.GetSettings();
DtCrowdAgentParams ap = new DtCrowdAgentParams();
ap.radius = settings.agentRadius;
ap.height = settings.agentHeight;
ap.maxAcceleration = settings.agentMaxAcceleration;
ap.maxSpeed = settings.agentMaxSpeed;
ap.collisionQueryRange = ap.radius * 12.0f;
ap.pathOptimizationRange = ap.radius * 30.0f;
ap.updateFlags = GetUpdateFlags();
ap.obstacleAvoidanceType = toolParams.m_obstacleAvoidanceType;
ap.separationWeight = toolParams.m_separationWeight;
return ap;
}
private int GetUpdateFlags()
{
int updateFlags = 0;
if (toolParams.m_anticipateTurns)
{
updateFlags |= DtCrowdAgentParams.DT_CROWD_ANTICIPATE_TURNS;
}
if (toolParams.m_optimizeVis)
{
updateFlags |= DtCrowdAgentParams.DT_CROWD_OPTIMIZE_VIS;
}
if (toolParams.m_optimizeTopo)
{
updateFlags |= DtCrowdAgentParams.DT_CROWD_OPTIMIZE_TOPO;
}
if (toolParams.m_obstacleAvoidance)
{
updateFlags |= DtCrowdAgentParams.DT_CROWD_OBSTACLE_AVOIDANCE;
}
if (toolParams.m_separation)
{
updateFlags |= DtCrowdAgentParams.DT_CROWD_SEPARATION;
}
return updateFlags;
}
public IRcToolable GetTool()
{
return _tool;
} }
public void Layout() public void Layout()
{ {
ImGui.Text("Options");
ImGui.Separator();
bool m_optimizeVis = toolParams.m_optimizeVis;
bool m_optimizeTopo = toolParams.m_optimizeTopo;
bool m_anticipateTurns = toolParams.m_anticipateTurns;
bool m_obstacleAvoidance = toolParams.m_obstacleAvoidance;
bool m_separation = toolParams.m_separation;
int m_obstacleAvoidanceType = toolParams.m_obstacleAvoidanceType;
float m_separationWeight = toolParams.m_separationWeight;
ImGui.Checkbox("Optimize Visibility", ref toolParams.m_optimizeVis);
ImGui.Checkbox("Optimize Topology", ref toolParams.m_optimizeTopo);
ImGui.Checkbox("Anticipate Turns", ref toolParams.m_anticipateTurns);
ImGui.Checkbox("Obstacle Avoidance", ref toolParams.m_obstacleAvoidance);
ImGui.SliderInt("Avoidance Quality", ref toolParams.m_obstacleAvoidanceType, 0, 3);
ImGui.Checkbox("Separation", ref toolParams.m_separation);
ImGui.SliderFloat("Separation Weight", ref toolParams.m_separationWeight, 0f, 20f, "%.2f");
ImGui.NewLine();
if (m_optimizeVis != toolParams.m_optimizeVis || m_optimizeTopo != toolParams.m_optimizeTopo
|| m_anticipateTurns != toolParams.m_anticipateTurns || m_obstacleAvoidance != toolParams.m_obstacleAvoidance
|| m_separation != toolParams.m_separation
|| m_obstacleAvoidanceType != toolParams.m_obstacleAvoidanceType
|| m_separationWeight != toolParams.m_separationWeight)
{
UpdateAgentParams();
}
ImGui.Text("Simulation Options"); ImGui.Text("Simulation Options");
ImGui.Separator(); ImGui.Separator();
ImGui.SliderInt("Agents", ref agents, 0, 10000); ImGui.SliderInt("Agents", ref agents, 0, 10000);
@ -80,6 +188,16 @@ public class CrowdProfilingTool
StartProfiling(); StartProfiling();
} }
if (m_optimizeVis != toolParams.m_optimizeVis || m_optimizeTopo != toolParams.m_optimizeTopo
|| m_anticipateTurns != toolParams.m_anticipateTurns || m_obstacleAvoidance != toolParams.m_obstacleAvoidance
|| m_separation != toolParams.m_separation
|| m_obstacleAvoidanceType != toolParams.m_obstacleAvoidanceType
|| m_separationWeight != toolParams.m_separationWeight)
{
UpdateAgentParams();
}
ImGui.Text("Times"); ImGui.Text("Times");
ImGui.Separator(); ImGui.Separator();
if (crowd != null) if (crowd != null)
@ -96,6 +214,11 @@ public class CrowdProfilingTool
} }
} }
public void HandleClick(RcVec3f s, RcVec3f p, bool shift)
{
//throw new NotImplementedException();
}
private DtStatus GetMobPosition(DtNavMeshQuery navquery, IDtQueryFilter filter, out RcVec3f randomPt) private DtStatus GetMobPosition(DtNavMeshQuery navquery, IDtQueryFilter filter, out RcVec3f randomPt)
{ {
return navquery.FindRandomPoint(filter, rnd, out var randomRef, out randomPt); return navquery.FindRandomPoint(filter, rnd, out var randomRef, out randomPt);
@ -395,15 +518,26 @@ public class CrowdProfilingTool
dd.DepthMask(true); dd.DepthMask(true);
} }
public void HandleUpdate(float dt)
{
Update(dt);
}
public void HandleClickRay(RcVec3f start, RcVec3f direction, bool shift)
{
//throw new NotImplementedException();
}
private DtCrowdAgent AddAgent(RcVec3f p, CrowdAgentType type) private DtCrowdAgent AddAgent(RcVec3f p, CrowdAgentType type)
{ {
DtCrowdAgentParams ap = agentParamsSupplier.Invoke(); DtCrowdAgentParams ap = GetAgentParams();
ap.userData = new CrowdAgentData(type, p); ap.userData = new CrowdAgentData(type, p);
return crowd.AddAgent(p, ap); return crowd.AddAgent(p, ap);
} }
public void UpdateAgentParams(int updateFlags, int obstacleAvoidanceType, float separationWeight) private void UpdateAgentParams()
{ {
int updateFlags = GetUpdateFlags();
if (crowd != null) if (crowd != null)
{ {
foreach (DtCrowdAgent ag in crowd.GetActiveAgents()) foreach (DtCrowdAgent ag in crowd.GetActiveAgents())
@ -418,8 +552,8 @@ public class CrowdProfilingTool
option.queryFilterType = ag.option.queryFilterType; option.queryFilterType = ag.option.queryFilterType;
option.userData = ag.option.userData; option.userData = ag.option.userData;
option.updateFlags = updateFlags; option.updateFlags = updateFlags;
option.obstacleAvoidanceType = obstacleAvoidanceType; option.obstacleAvoidanceType = toolParams.m_obstacleAvoidanceType;
option.separationWeight = separationWeight; option.separationWeight = toolParams.m_separationWeight;
crowd.UpdateAgentParameters(ag, option); crowd.UpdateAgentParameters(ag, option);
} }
} }

View File

@ -35,16 +35,15 @@ using static DotRecast.Recast.Demo.Draw.DebugDrawPrimitives;
namespace DotRecast.Recast.Demo.Tools; namespace DotRecast.Recast.Demo.Tools;
public class CrowdSampleTool : ISampleTool public class CrowdampleTool : ISampleTool
{ {
private static readonly ILogger Logger = Log.ForContext<CrowdSampleTool>(); private static readonly ILogger Logger = Log.ForContext<CrowdampleTool>();
private DemoSample _sample; private DemoSample _sample;
private readonly RcCrowdTool _tool; private readonly RcCrowdTool _tool;
private readonly CrowdToolParams toolParams = new CrowdToolParams(); private readonly CrowdToolParams toolParams = new CrowdToolParams();
private DtNavMesh m_nav; private DtNavMesh m_nav;
private DtCrowd crowd; private DtCrowd crowd;
private readonly CrowdProfilingTool profilingTool;
private readonly DtCrowdAgentDebugInfo m_agentDebug = new DtCrowdAgentDebugInfo(); private readonly DtCrowdAgentDebugInfo m_agentDebug = new DtCrowdAgentDebugInfo();
private readonly Dictionary<long, CrowdAgentTrail> m_trails = new(); private readonly Dictionary<long, CrowdAgentTrail> m_trails = new();
@ -54,10 +53,9 @@ public class CrowdSampleTool : ISampleTool
private int m_modeIdx = CrowdToolMode.CREATE.Idx; private int m_modeIdx = CrowdToolMode.CREATE.Idx;
private long crowdUpdateTime; private long crowdUpdateTime;
public CrowdSampleTool() public CrowdampleTool()
{ {
m_agentDebug.vod = new DtObstacleAvoidanceDebugData(2048); m_agentDebug.vod = new DtObstacleAvoidanceDebugData(2048);
profilingTool = new CrowdProfilingTool(GetAgentParams);
_tool = new(); _tool = new();
} }
@ -118,18 +116,11 @@ public class CrowdSampleTool : ISampleTool
option.adaptiveDepth = 3; option.adaptiveDepth = 3;
crowd.SetObstacleAvoidanceParams(3, option); crowd.SetObstacleAvoidanceParams(3, option);
profilingTool.Setup(settings.agentRadius, m_nav);
} }
} }
public void HandleClick(RcVec3f s, RcVec3f p, bool shift) public void HandleClick(RcVec3f s, RcVec3f p, bool shift)
{ {
if (m_mode == CrowdToolMode.PROFILING)
{
return;
}
if (crowd == null) if (crowd == null)
{ {
return; return;
@ -326,12 +317,6 @@ public class CrowdSampleTool : ISampleTool
public void HandleRender(NavMeshRenderer renderer) public void HandleRender(NavMeshRenderer renderer)
{ {
if (m_mode == CrowdToolMode.PROFILING)
{
profilingTool.HandleRender(renderer);
return;
}
RecastDebugDraw dd = renderer.GetDebugDraw(); RecastDebugDraw dd = renderer.GetDebugDraw();
var settings = _sample.GetSettings(); var settings = _sample.GetSettings();
float rad = settings.agentRadius; float rad = settings.agentRadius;
@ -639,14 +624,9 @@ public class CrowdSampleTool : ISampleTool
private void UpdateTick(float dt) private void UpdateTick(float dt)
{ {
if (m_mode == CrowdToolMode.PROFILING)
{
profilingTool.Update(dt);
return;
}
if (crowd == null) if (crowd == null)
return; return;
DtNavMesh nav = _sample.GetNavMesh(); DtNavMesh nav = _sample.GetNavMesh();
if (nav == null) if (nav == null)
return; return;
@ -686,7 +666,6 @@ public class CrowdSampleTool : ISampleTool
ImGui.RadioButton(CrowdToolMode.MOVE_TARGET.Label, ref m_modeIdx, CrowdToolMode.MOVE_TARGET.Idx); ImGui.RadioButton(CrowdToolMode.MOVE_TARGET.Label, ref m_modeIdx, CrowdToolMode.MOVE_TARGET.Idx);
ImGui.RadioButton(CrowdToolMode.SELECT.Label, ref m_modeIdx, CrowdToolMode.SELECT.Idx); ImGui.RadioButton(CrowdToolMode.SELECT.Label, ref m_modeIdx, CrowdToolMode.SELECT.Idx);
ImGui.RadioButton(CrowdToolMode.TOGGLE_POLYS.Label, ref m_modeIdx, CrowdToolMode.TOGGLE_POLYS.Idx); ImGui.RadioButton(CrowdToolMode.TOGGLE_POLYS.Label, ref m_modeIdx, CrowdToolMode.TOGGLE_POLYS.Idx);
ImGui.RadioButton(CrowdToolMode.PROFILING.Label, ref m_modeIdx, CrowdToolMode.PROFILING.Idx);
ImGui.NewLine(); ImGui.NewLine();
if (previousToolMode.Idx != m_modeIdx) if (previousToolMode.Idx != m_modeIdx)
@ -722,29 +701,21 @@ public class CrowdSampleTool : ISampleTool
} }
if (m_mode == CrowdToolMode.PROFILING) ImGui.Text("Selected Debug Draw");
{ ImGui.Separator();
profilingTool.Layout(); ImGui.Checkbox("Show Corners", ref toolParams.m_showCorners);
} ImGui.Checkbox("Show Collision Segs", ref toolParams.m_showCollisionSegments);
ImGui.Checkbox("Show Path", ref toolParams.m_showPath);
ImGui.Checkbox("Show VO", ref toolParams.m_showVO);
ImGui.Checkbox("Show Path Optimization", ref toolParams.m_showOpt);
ImGui.Checkbox("Show Neighbours", ref toolParams.m_showNeis);
ImGui.NewLine();
if (m_mode != CrowdToolMode.PROFILING) ImGui.Text("Debug Draw");
{ ImGui.Separator();
ImGui.Text("Selected Debug Draw"); ImGui.Checkbox("Show Proximity Grid", ref toolParams.m_showGrid);
ImGui.Separator(); ImGui.Checkbox("Show Nodes", ref toolParams.m_showNodes);
ImGui.Checkbox("Show Corners", ref toolParams.m_showCorners); ImGui.Text($"Update Time: {crowdUpdateTime} ms");
ImGui.Checkbox("Show Collision Segs", ref toolParams.m_showCollisionSegments);
ImGui.Checkbox("Show Path", ref toolParams.m_showPath);
ImGui.Checkbox("Show VO", ref toolParams.m_showVO);
ImGui.Checkbox("Show Path Optimization", ref toolParams.m_showOpt);
ImGui.Checkbox("Show Neighbours", ref toolParams.m_showNeis);
ImGui.NewLine();
ImGui.Text("Debug Draw");
ImGui.Separator();
ImGui.Checkbox("Show Proximity Grid", ref toolParams.m_showGrid);
ImGui.Checkbox("Show Nodes", ref toolParams.m_showNodes);
ImGui.Text($"Update Time: {crowdUpdateTime} ms");
}
} }
private void UpdateAgentParams() private void UpdateAgentParams()
@ -755,7 +726,6 @@ public class CrowdSampleTool : ISampleTool
} }
int updateFlags = GetUpdateFlags(); int updateFlags = GetUpdateFlags();
profilingTool.UpdateAgentParams(updateFlags, toolParams.m_obstacleAvoidanceType, toolParams.m_separationWeight);
foreach (DtCrowdAgent ag in crowd.GetActiveAgents()) foreach (DtCrowdAgent ag in crowd.GetActiveAgents())
{ {
DtCrowdAgentParams option = new DtCrowdAgentParams(); DtCrowdAgentParams option = new DtCrowdAgentParams();

View File

@ -8,14 +8,12 @@ namespace DotRecast.Recast.Toolset.Tools
public static readonly CrowdToolMode MOVE_TARGET = new CrowdToolMode(1, "Move Target"); public static readonly CrowdToolMode MOVE_TARGET = new CrowdToolMode(1, "Move Target");
public static readonly CrowdToolMode SELECT = new CrowdToolMode(2, "Select Agent"); public static readonly CrowdToolMode SELECT = new CrowdToolMode(2, "Select Agent");
public static readonly CrowdToolMode TOGGLE_POLYS = new CrowdToolMode(3, "Toggle Polys"); public static readonly CrowdToolMode TOGGLE_POLYS = new CrowdToolMode(3, "Toggle Polys");
public static readonly CrowdToolMode PROFILING = new CrowdToolMode(4, "Profiling");
public static readonly RcImmutableArray<CrowdToolMode> Values = RcImmutableArray.Create( public static readonly RcImmutableArray<CrowdToolMode> Values = RcImmutableArray.Create(
CREATE, CREATE,
MOVE_TARGET, MOVE_TARGET,
SELECT, SELECT,
TOGGLE_POLYS, TOGGLE_POLYS
PROFILING
); );
public int Idx { get; } public int Idx { get; }

View File

@ -1,21 +1,3 @@
/*
recast4j copyright (c) 2020-2021 Piotr Piastucki piotr@jtilia.org
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
namespace DotRecast.Recast.Toolset.Tools namespace DotRecast.Recast.Toolset.Tools
{ {
public class CrowdToolParams public class CrowdToolParams

View File

@ -9,7 +9,7 @@ namespace DotRecast.Recast.Toolset.Tools
{ {
public string GetName() public string GetName()
{ {
return "Create Convex Volumes"; return "Convex Volumes";
} }
public RcConvexVolume RemoveByPos(IInputGeomProvider geom, RcVec3f pos) public RcConvexVolume RemoveByPos(IInputGeomProvider geom, RcVec3f pos)

View File

@ -0,0 +1,10 @@
namespace DotRecast.Recast.Toolset.Tools
{
public class RcCrowdProfilingTool : IRcToolable
{
public string GetName()
{
return "Crowd Profiling";
}
}
}

View File

@ -4,7 +4,7 @@
{ {
public string GetName() public string GetName()
{ {
return "Create Crowd"; return "Crowd Control";
} }
} }
} }

View File

@ -25,7 +25,7 @@ namespace DotRecast.Recast.Toolset.Tools
public string GetName() public string GetName()
{ {
return "Create Temp Obstacles"; return "Temp Obstacles";
} }
public NavMeshBuildResult Build(IInputGeomProvider geom, RcNavMeshBuildSettings setting, RcByteOrder order, bool cCompatibility) public NavMeshBuildResult Build(IInputGeomProvider geom, RcNavMeshBuildSettings setting, RcByteOrder order, bool cCompatibility)

View File

@ -16,7 +16,7 @@ namespace DotRecast.Recast.Toolset.Tools
public string GetName() public string GetName()
{ {
return "Create Off-Mesh Links"; return "Off-Mesh Links";
} }
public RcOffMeshConnectionToolOption GetOption() public RcOffMeshConnectionToolOption GetOption()

View File

@ -10,7 +10,7 @@ namespace DotRecast.Recast.Toolset.Tools
{ {
public string GetName() public string GetName()
{ {
return "Create Tiles"; return "Tiles";
} }
public void RemoveAllTiles(IInputGeomProvider geom, RcNavMeshBuildSettings settings, DtNavMesh navMesh) public void RemoveAllTiles(IInputGeomProvider geom, RcNavMeshBuildSettings settings, DtNavMesh navMesh)