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 OffMeshConnectionSampleTool(),
new ConvexVolumeSampleTool(),
new CrowdSampleTool(),
new CrowdampleTool(),
new CrowdProfilingSampleTool(),
new JumpLinkBuilderSampleTool(),
new DynamicUpdateSampleTool()
);

View File

@ -28,13 +28,21 @@ using DotRecast.Recast.Demo.Draw;
using DotRecast.Recast.Toolset;
using DotRecast.Recast.Toolset.Tools;
using ImGuiNET;
using Serilog;
using static DotRecast.Recast.Demo.Draw.DebugDraw;
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 expandCrowdOptions = 1;
private int agents = 1000;
@ -52,13 +60,113 @@ public class CrowdProfilingTool
private readonly List<DtPolyPoint> _polyPoints = new();
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()
{
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.Separator();
ImGui.SliderInt("Agents", ref agents, 0, 10000);
@ -80,6 +188,16 @@ public class CrowdProfilingTool
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.Separator();
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)
{
return navquery.FindRandomPoint(filter, rnd, out var randomRef, out randomPt);
@ -395,15 +518,26 @@ public class CrowdProfilingTool
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)
{
DtCrowdAgentParams ap = agentParamsSupplier.Invoke();
DtCrowdAgentParams ap = GetAgentParams();
ap.userData = new CrowdAgentData(type, p);
return crowd.AddAgent(p, ap);
}
public void UpdateAgentParams(int updateFlags, int obstacleAvoidanceType, float separationWeight)
private void UpdateAgentParams()
{
int updateFlags = GetUpdateFlags();
if (crowd != null)
{
foreach (DtCrowdAgent ag in crowd.GetActiveAgents())
@ -418,8 +552,8 @@ public class CrowdProfilingTool
option.queryFilterType = ag.option.queryFilterType;
option.userData = ag.option.userData;
option.updateFlags = updateFlags;
option.obstacleAvoidanceType = obstacleAvoidanceType;
option.separationWeight = separationWeight;
option.obstacleAvoidanceType = toolParams.m_obstacleAvoidanceType;
option.separationWeight = toolParams.m_separationWeight;
crowd.UpdateAgentParameters(ag, option);
}
}

View File

@ -35,16 +35,15 @@ using static DotRecast.Recast.Demo.Draw.DebugDrawPrimitives;
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 readonly RcCrowdTool _tool;
private readonly CrowdToolParams toolParams = new CrowdToolParams();
private DtNavMesh m_nav;
private DtCrowd crowd;
private readonly CrowdProfilingTool profilingTool;
private readonly DtCrowdAgentDebugInfo m_agentDebug = new DtCrowdAgentDebugInfo();
private readonly Dictionary<long, CrowdAgentTrail> m_trails = new();
@ -54,10 +53,9 @@ public class CrowdSampleTool : ISampleTool
private int m_modeIdx = CrowdToolMode.CREATE.Idx;
private long crowdUpdateTime;
public CrowdSampleTool()
public CrowdampleTool()
{
m_agentDebug.vod = new DtObstacleAvoidanceDebugData(2048);
profilingTool = new CrowdProfilingTool(GetAgentParams);
_tool = new();
}
@ -118,18 +116,11 @@ public class CrowdSampleTool : ISampleTool
option.adaptiveDepth = 3;
crowd.SetObstacleAvoidanceParams(3, option);
profilingTool.Setup(settings.agentRadius, m_nav);
}
}
public void HandleClick(RcVec3f s, RcVec3f p, bool shift)
{
if (m_mode == CrowdToolMode.PROFILING)
{
return;
}
if (crowd == null)
{
return;
@ -326,12 +317,6 @@ public class CrowdSampleTool : ISampleTool
public void HandleRender(NavMeshRenderer renderer)
{
if (m_mode == CrowdToolMode.PROFILING)
{
profilingTool.HandleRender(renderer);
return;
}
RecastDebugDraw dd = renderer.GetDebugDraw();
var settings = _sample.GetSettings();
float rad = settings.agentRadius;
@ -639,14 +624,9 @@ public class CrowdSampleTool : ISampleTool
private void UpdateTick(float dt)
{
if (m_mode == CrowdToolMode.PROFILING)
{
profilingTool.Update(dt);
return;
}
if (crowd == null)
return;
DtNavMesh nav = _sample.GetNavMesh();
if (nav == null)
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.SELECT.Label, ref m_modeIdx, CrowdToolMode.SELECT.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();
if (previousToolMode.Idx != m_modeIdx)
@ -722,13 +701,6 @@ public class CrowdSampleTool : ISampleTool
}
if (m_mode == CrowdToolMode.PROFILING)
{
profilingTool.Layout();
}
if (m_mode != CrowdToolMode.PROFILING)
{
ImGui.Text("Selected Debug Draw");
ImGui.Separator();
ImGui.Checkbox("Show Corners", ref toolParams.m_showCorners);
@ -745,7 +717,6 @@ public class CrowdSampleTool : ISampleTool
ImGui.Checkbox("Show Nodes", ref toolParams.m_showNodes);
ImGui.Text($"Update Time: {crowdUpdateTime} ms");
}
}
private void UpdateAgentParams()
{
@ -755,7 +726,6 @@ public class CrowdSampleTool : ISampleTool
}
int updateFlags = GetUpdateFlags();
profilingTool.UpdateAgentParams(updateFlags, toolParams.m_obstacleAvoidanceType, toolParams.m_separationWeight);
foreach (DtCrowdAgent ag in crowd.GetActiveAgents())
{
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 SELECT = new CrowdToolMode(2, "Select Agent");
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(
CREATE,
MOVE_TARGET,
SELECT,
TOGGLE_POLYS,
PROFILING
TOGGLE_POLYS
);
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
{
public class CrowdToolParams

View File

@ -9,7 +9,7 @@ namespace DotRecast.Recast.Toolset.Tools
{
public string GetName()
{
return "Create Convex Volumes";
return "Convex Volumes";
}
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()
{
return "Create Crowd";
return "Crowd Control";
}
}
}

View File

@ -25,7 +25,7 @@ namespace DotRecast.Recast.Toolset.Tools
public string GetName()
{
return "Create Temp Obstacles";
return "Temp Obstacles";
}
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()
{
return "Create Off-Mesh Links";
return "Off-Mesh Links";
}
public RcOffMeshConnectionToolOption GetOption()

View File

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