completed crowd tool

This commit is contained in:
ikpil 2023-03-26 12:57:40 +09:00
parent 4d19a86c11
commit 9168ed0f04
2 changed files with 174 additions and 176 deletions

View File

@ -19,6 +19,7 @@ freely, subject to the following restrictions:
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using DotRecast.Core; using DotRecast.Core;
using DotRecast.Detour; using DotRecast.Detour;
using DotRecast.Detour.Crowd; using DotRecast.Detour.Crowd;
@ -55,92 +56,93 @@ public class CrowdProfilingTool
this.agentParamsSupplier = agentParamsSupplier; this.agentParamsSupplier = agentParamsSupplier;
} }
public void layout(IWindow ctx) public void layout()
{ {
// nk_layout_row_dynamic(ctx, 1, 1); ImGui.Text("Simulation Options");
// nk_spacing(ctx, 1); ImGui.Separator();
// if (nk_tree_state_push(ctx, 0, "Simulation Options", expandSimOptions)) {
// nk_layout_row_dynamic(ctx, 20, 1);
ImGui.SliderInt("Agents", ref agents, 0, 10000); ImGui.SliderInt("Agents", ref agents, 0, 10000);
// nk_layout_row_dynamic(ctx, 20, 1);
ImGui.SliderInt("Random Seed", ref randomSeed, 0, 1024); ImGui.SliderInt("Random Seed", ref randomSeed, 0, 1024);
// nk_layout_row_dynamic(ctx, 20, 1);
ImGui.SliderInt("Number of Zones", ref numberOfZones, 0, 10); ImGui.SliderInt("Number of Zones", ref numberOfZones, 0, 10);
// nk_layout_row_dynamic(ctx, 20, 1);
ImGui.SliderFloat("Zone Radius", ref zoneRadius, 0, 100, "%.0f"); ImGui.SliderFloat("Zone Radius", ref zoneRadius, 0, 100, "%.0f");
// nk_layout_row_dynamic(ctx, 20, 1);
ImGui.SliderFloat("Mobs %", ref percentMobs, 0, 100, "%.0f"); ImGui.SliderFloat("Mobs %", ref percentMobs, 0, 100, "%.0f");
// nk_layout_row_dynamic(ctx, 20, 1);
ImGui.SliderFloat("Travellers %", ref percentTravellers, 0, 100, "%.0f"); ImGui.SliderFloat("Travellers %", ref percentTravellers, 0, 100, "%.0f");
// nk_tree_state_pop(ctx); ImGui.NewLine();
// }
// if (nk_tree_state_push(ctx, 0, "Crowd Options", expandCrowdOptions)) { ImGui.Text("Crowd Options");
// nk_layout_row_dynamic(ctx, 20, 1); ImGui.Separator();
ImGui.SliderInt("Path Queue Size", ref pathQueueSize, 0, 1024); ImGui.SliderInt("Path Queue Size", ref pathQueueSize, 0, 1024);
// nk_layout_row_dynamic(ctx, 20, 1);
ImGui.SliderInt("Max Iterations", ref maxIterations, 0, 4000); ImGui.SliderInt("Max Iterations", ref maxIterations, 0, 4000);
// nk_tree_state_pop(ctx); ImGui.NewLine();
// }
// nk_layout_row_dynamic(ctx, 1, 1); if (ImGui.Button("Start"))
// nk_spacing(ctx, 1); {
// nk_layout_row_dynamic(ctx, 20, 1); if (navMesh != null)
// if (nk_button_text(ctx, "Start")) { {
// if (navMesh != null) { rnd = new NavMeshQuery.FRand(randomSeed);
// rnd = new NavMeshQuery.FRand(randomSeed[0]); createCrowd();
// createCrowd(); createZones();
// createZones(); NavMeshQuery navquery = new NavMeshQuery(navMesh);
// NavMeshQuery navquery = new NavMeshQuery(navMesh); QueryFilter filter = new DefaultQueryFilter();
// QueryFilter filter = new DefaultQueryFilter(); for (int i = 0; i < agents; i++)
// for (int i = 0; i < agents[0]; i++) { {
// float tr = rnd.frand(); float tr = rnd.frand();
// AgentType type = AgentType.MOB; AgentType type = AgentType.MOB;
// float mobsPcnt = percentMobs[0] / 100f; float mobsPcnt = percentMobs / 100f;
// if (tr > mobsPcnt) { if (tr > mobsPcnt)
// tr = rnd.frand(); {
// float travellerPcnt = percentTravellers[0] / 100f; tr = rnd.frand();
// if (tr > travellerPcnt) { float travellerPcnt = percentTravellers / 100f;
// type = AgentType.VILLAGER; if (tr > travellerPcnt)
// } else { {
// type = AgentType.TRAVELLER; type = AgentType.VILLAGER;
// } }
// } else
// float[] pos = null; {
// switch (type) { type = AgentType.TRAVELLER;
// case MOB: }
// pos = getMobPosition(navquery, filter, pos); }
// break;
// case VILLAGER: float[] pos = null;
// pos = getVillagerPosition(navquery, filter, pos); switch (type)
// break; {
// case TRAVELLER: case AgentType.MOB:
// pos = getVillagerPosition(navquery, filter, pos); pos = getMobPosition(navquery, filter, pos);
// break; break;
// } case AgentType.VILLAGER:
// if (pos != null) { pos = getVillagerPosition(navquery, filter, pos);
// addAgent(pos, type); break;
// } case AgentType.TRAVELLER:
// } pos = getVillagerPosition(navquery, filter, pos);
// } break;
// } }
// if (crowd != null) {
// nk_layout_row_dynamic(ctx, 18, 1); if (pos != null)
// nk_label(ctx, string.format("Max time to enqueue request: %.3f s", crowd.telemetry().maxTimeToEnqueueRequest()), {
// NK_TEXT_ALIGN_LEFT); addAgent(pos, type);
// nk_layout_row_dynamic(ctx, 18, 1); }
// nk_label(ctx, string.format("Max time to find path: %.3f s", crowd.telemetry().maxTimeToFindPath()), }
// NK_TEXT_ALIGN_LEFT); }
// List<Tuple<string, long>> timings = crowd.telemetry().executionTimings().entrySet().stream() }
// .map(e => Tuple.Create(e.getKey(), e.getValue())).sorted((t1, t2) => long.compare(t2.Item2, t1.Item2))
// .collect(toList()); ImGui.Text("Times");
// foreach (Tuple<string, long> e in timings) { ImGui.Separator();
// nk_layout_row_dynamic(ctx, 18, 1); if (crowd != null)
// nk_label(ctx, string.format("%s: %d us", e.Item1, e.Item2 / 1_000), NK_TEXT_ALIGN_LEFT); {
// } ImGui.Text($"Max time to enqueue request: {crowd.telemetry().maxTimeToEnqueueRequest()} s");
// nk_layout_row_dynamic(ctx, 1, 1); ImGui.Text($"Max time to find path: {crowd.telemetry().maxTimeToFindPath()} s");
// nk_spacing(ctx, 1); List<Tuple<string, long>> timings = crowd.telemetry()
// nk_layout_row_dynamic(ctx, 18, 1); .executionTimings()
// nk_label(ctx, string.format("Update Time: %d ms", crowdUpdateTime), NK_TEXT_ALIGN_LEFT); .Select(e => Tuple.Create(e.Key, e.Value))
// } .OrderBy(x => x.Item2)
.ToList();
foreach (Tuple<string, long> e in timings)
{
ImGui.Text($"{e.Item1}: {e.Item2 / 1_000} us");
}
ImGui.Text($"Update Time: {crowdUpdateTime} ms");
}
} }
private float[] getMobPosition(NavMeshQuery navquery, QueryFilter filter, float[] pos) private float[] getMobPosition(NavMeshQuery navquery, QueryFilter filter, float[] pos)

View File

@ -19,6 +19,7 @@ freely, subject to the following restrictions:
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using Silk.NET.Windowing; using Silk.NET.Windowing;
using DotRecast.Detour; using DotRecast.Detour;
@ -34,17 +35,34 @@ using static DotRecast.Core.RecastMath;
namespace DotRecast.Recast.Demo.Tools; namespace DotRecast.Recast.Demo.Tools;
public class CrowdTool : Tool public class CrowdToolMode
{ {
private enum ToolMode public static readonly CrowdToolMode CREATE = new(0, "Create Agents");
{ public static readonly CrowdToolMode MOVE_TARGET = new(1, "Move Target");
public static readonly CrowdToolMode SELECT = new(2, "Select Agent");
public static readonly CrowdToolMode TOGGLE_POLYS = new(3, "Toggle Polys");
public static readonly CrowdToolMode PROFILING = new(4, "Profiling");
public static readonly ImmutableArray<CrowdToolMode> Values = ImmutableArray.Create(
CREATE, CREATE,
MOVE_TARGET, MOVE_TARGET,
SELECT, SELECT,
TOGGLE_POLYS, TOGGLE_POLYS,
PROFILING PROFILING
} );
public int Idx { get; }
public string Label { get; }
private CrowdToolMode(int idx, string label)
{
Idx = idx;
Label = label;
}
}
public class CrowdTool : Tool
{
private readonly CrowdToolParams toolParams = new CrowdToolParams(); private readonly CrowdToolParams toolParams = new CrowdToolParams();
private Sample sample; private Sample sample;
private NavMesh m_nav; private NavMesh m_nav;
@ -63,7 +81,8 @@ public class CrowdTool : Tool
private readonly Dictionary<long, AgentTrail> m_trails = new(); private readonly Dictionary<long, AgentTrail> m_trails = new();
private float[] m_targetPos; private float[] m_targetPos;
private long m_targetRef; private long m_targetRef;
private ToolMode m_mode = ToolMode.CREATE; private CrowdToolMode m_mode = CrowdToolMode.CREATE;
private int m_modeIdx = CrowdToolMode.CREATE.Idx;
private long crowdUpdateTime; private long crowdUpdateTime;
public CrowdTool() public CrowdTool()
@ -129,7 +148,7 @@ public class CrowdTool : Tool
public override void handleClick(float[] s, float[] p, bool shift) public override void handleClick(float[] s, float[] p, bool shift)
{ {
if (m_mode == ToolMode.PROFILING) if (m_mode == CrowdToolMode.PROFILING)
{ {
return; return;
} }
@ -139,7 +158,7 @@ public class CrowdTool : Tool
return; return;
} }
if (m_mode == ToolMode.CREATE) if (m_mode == CrowdToolMode.CREATE)
{ {
if (shift) if (shift)
{ {
@ -156,17 +175,17 @@ public class CrowdTool : Tool
addAgent(p); addAgent(p);
} }
} }
else if (m_mode == ToolMode.MOVE_TARGET) else if (m_mode == CrowdToolMode.MOVE_TARGET)
{ {
setMoveTarget(p, shift); setMoveTarget(p, shift);
} }
else if (m_mode == ToolMode.SELECT) else if (m_mode == CrowdToolMode.SELECT)
{ {
// Highlight // Highlight
CrowdAgent ahit = hitTestAgents(s, p); CrowdAgent ahit = hitTestAgents(s, p);
hilightAgent(ahit); hilightAgent(ahit);
} }
else if (m_mode == ToolMode.TOGGLE_POLYS) else if (m_mode == CrowdToolMode.TOGGLE_POLYS)
{ {
NavMesh nav = sample.getNavMesh(); NavMesh nav = sample.getNavMesh();
NavMeshQuery navquery = sample.getNavMeshQuery(); NavMeshQuery navquery = sample.getNavMeshQuery();
@ -332,7 +351,7 @@ public class CrowdTool : Tool
public override void handleRender(NavMeshRenderer renderer) public override void handleRender(NavMeshRenderer renderer)
{ {
if (m_mode == ToolMode.PROFILING) if (m_mode == CrowdToolMode.PROFILING)
{ {
profilingTool.handleRender(renderer); profilingTool.handleRender(renderer);
return; return;
@ -647,7 +666,7 @@ public class CrowdTool : Tool
private void updateTick(float dt) private void updateTick(float dt)
{ {
if (m_mode == ToolMode.PROFILING) if (m_mode == CrowdToolMode.PROFILING)
{ {
profilingTool.update(dt); profilingTool.update(dt);
return; return;
@ -687,95 +706,72 @@ public class CrowdTool : Tool
public override void layout() public override void layout()
{ {
// ToolMode previousToolMode = m_mode; ImGui.Text($"Crowd Tool Mode");
// nk_layout_row_dynamic(ctx, 20, 1); ImGui.Separator();
// if (nk_option_label(ctx, "Create Agents", m_mode == ToolMode.CREATE)) { CrowdToolMode previousToolMode = m_mode;
// m_mode = ToolMode.CREATE; ImGui.RadioButton(CrowdToolMode.CREATE.Label, ref m_modeIdx, CrowdToolMode.CREATE.Idx);
// } ImGui.RadioButton(CrowdToolMode.MOVE_TARGET.Label, ref m_modeIdx, CrowdToolMode.MOVE_TARGET.Idx);
// nk_layout_row_dynamic(ctx, 20, 1); ImGui.RadioButton(CrowdToolMode.SELECT.Label, ref m_modeIdx, CrowdToolMode.SELECT.Idx);
// if (nk_option_label(ctx, "Move Target", m_mode == ToolMode.MOVE_TARGET)) { ImGui.RadioButton(CrowdToolMode.TOGGLE_POLYS.Label, ref m_modeIdx, CrowdToolMode.TOGGLE_POLYS.Idx);
// m_mode = ToolMode.MOVE_TARGET; ImGui.RadioButton(CrowdToolMode.PROFILING.Label, ref m_modeIdx, CrowdToolMode.PROFILING.Idx);
// } ImGui.NewLine();
// nk_layout_row_dynamic(ctx, 20, 1);
// if (nk_option_label(ctx, "Select Agent", m_mode == ToolMode.SELECT)) { if (previousToolMode.Idx != m_modeIdx)
// m_mode = ToolMode.SELECT; {
// } m_mode = CrowdToolMode.Values[m_modeIdx];
// nk_layout_row_dynamic(ctx, 20, 1); }
// if (nk_option_label(ctx, "Toggle Polys", m_mode == ToolMode.TOGGLE_POLYS)) {
// m_mode = ToolMode.TOGGLE_POLYS; ImGui.Text("Options");
// } ImGui.Separator();
// nk_layout_row_dynamic(ctx, 20, 1); bool m_optimizeVis = toolParams.m_optimizeVis;
// if (nk_option_label(ctx, "Profiling", m_mode == ToolMode.PROFILING)) { bool m_optimizeTopo = toolParams.m_optimizeTopo;
// m_mode = ToolMode.PROFILING; bool m_anticipateTurns = toolParams.m_anticipateTurns;
// } bool m_obstacleAvoidance = toolParams.m_obstacleAvoidance;
// nk_layout_row_dynamic(ctx, 1, 1); bool m_separation = toolParams.m_separation;
// nk_spacing(ctx, 1); int m_obstacleAvoidanceType = toolParams.m_obstacleAvoidanceType;
// if (nk_tree_state_push(ctx, 0, "Options", toolParams.m_expandOptions)) { float m_separationWeight = toolParams.m_separationWeight;
// bool m_optimizeVis = toolParams.m_optimizeVis; toolParams.m_optimizeVis = ImGui.RadioButton("Optimize Visibility", toolParams.m_optimizeVis);
// bool m_optimizeTopo = toolParams.m_optimizeTopo; toolParams.m_optimizeTopo = ImGui.RadioButton("Optimize Topology", toolParams.m_optimizeTopo);
// bool m_anticipateTurns = toolParams.m_anticipateTurns; toolParams.m_anticipateTurns = ImGui.RadioButton("Anticipate Turns", toolParams.m_anticipateTurns);
// bool m_obstacleAvoidance = toolParams.m_obstacleAvoidance; toolParams.m_obstacleAvoidance = ImGui.RadioButton("Obstacle Avoidance", toolParams.m_obstacleAvoidance);
// bool m_separation = toolParams.m_separation;
// int m_obstacleAvoidanceType = toolParams.m_obstacleAvoidanceType[0];
// float m_separationWeight = toolParams.m_separationWeight[0];
// nk_layout_row_dynamic(ctx, 20, 1);
// toolParams.m_optimizeVis = nk_option_text(ctx, "Optimize Visibility", toolParams.m_optimizeVis);
// nk_layout_row_dynamic(ctx, 20, 1);
// toolParams.m_optimizeTopo = nk_option_text(ctx, "Optimize Topology", toolParams.m_optimizeTopo);
// nk_layout_row_dynamic(ctx, 20, 1);
// toolParams.m_anticipateTurns = nk_option_text(ctx, "Anticipate Turns", toolParams.m_anticipateTurns);
// nk_layout_row_dynamic(ctx, 20, 1);
// toolParams.m_obstacleAvoidance = nk_option_text(ctx, "Obstacle Avoidance", toolParams.m_obstacleAvoidance);
// nk_layout_row_dynamic(ctx, 20, 1);
ImGui.SliderInt("Avoidance Quality", ref toolParams.m_obstacleAvoidanceType, 0, 3); ImGui.SliderInt("Avoidance Quality", ref toolParams.m_obstacleAvoidanceType, 0, 3);
// nk_layout_row_dynamic(ctx, 20, 1); toolParams.m_separation = ImGui.RadioButton("Separation", toolParams.m_separation);
// toolParams.m_separation = nk_option_text(ctx, "Separation", toolParams.m_separation);
// nk_layout_row_dynamic(ctx, 20, 1);
ImGui.SliderFloat("Separation Weight", ref toolParams.m_separationWeight, 0f, 20f, "%.2f"); ImGui.SliderFloat("Separation Weight", ref toolParams.m_separationWeight, 0f, 20f, "%.2f");
// if (m_optimizeVis != toolParams.m_optimizeVis || m_optimizeTopo != toolParams.m_optimizeTopo ImGui.NewLine();
// || m_anticipateTurns != toolParams.m_anticipateTurns || m_obstacleAvoidance != toolParams.m_obstacleAvoidance
// || m_separation != toolParams.m_separation if (m_optimizeVis != toolParams.m_optimizeVis || m_optimizeTopo != toolParams.m_optimizeTopo
// || m_obstacleAvoidanceType != toolParams.m_obstacleAvoidanceType[0] || m_anticipateTurns != toolParams.m_anticipateTurns || m_obstacleAvoidance != toolParams.m_obstacleAvoidance
// || m_separationWeight != toolParams.m_separationWeight[0]) { || m_separation != toolParams.m_separation
// updateAgentParams(); || m_obstacleAvoidanceType != toolParams.m_obstacleAvoidanceType
// } || m_separationWeight != toolParams.m_separationWeight)
// nk_tree_state_pop(ctx); {
// } updateAgentParams();
// if (m_mode == ToolMode.PROFILING) { }
// profilingTool.layout(ctx);
// }
// if (m_mode != ToolMode.PROFILING) { if (m_mode == CrowdToolMode.PROFILING)
// nk_layout_row_dynamic(ctx, 1, 1); {
// nk_spacing(ctx, 1); profilingTool.layout();
// if (nk_tree_state_push(ctx, 0, "Selected Debug Draw", toolParams.m_expandSelectedDebugDraw)) { }
// nk_layout_row_dynamic(ctx, 20, 1);
// toolParams.m_showCorners = nk_option_text(ctx, "Show Corners", toolParams.m_showCorners); if (m_mode != CrowdToolMode.PROFILING)
// nk_layout_row_dynamic(ctx, 20, 1); {
// toolParams.m_showCollisionSegments = nk_option_text(ctx, "Show Collision Segs", toolParams.m_showCollisionSegments); ImGui.Text("Selected Debug Draw");
// nk_layout_row_dynamic(ctx, 20, 1); ImGui.Separator();
// toolParams.m_showPath = nk_option_text(ctx, "Show Path", toolParams.m_showPath); toolParams.m_showCorners = ImGui.RadioButton("Show Corners", toolParams.m_showCorners);
// nk_layout_row_dynamic(ctx, 20, 1); toolParams.m_showCollisionSegments = ImGui.RadioButton("Show Collision Segs", toolParams.m_showCollisionSegments);
// toolParams.m_showVO = nk_option_text(ctx, "Show VO", toolParams.m_showVO); toolParams.m_showPath = ImGui.RadioButton("Show Path", toolParams.m_showPath);
// nk_layout_row_dynamic(ctx, 20, 1); toolParams.m_showVO = ImGui.RadioButton("Show VO", toolParams.m_showVO);
// toolParams.m_showOpt = nk_option_text(ctx, "Show Path Optimization", toolParams.m_showOpt); toolParams.m_showOpt = ImGui.RadioButton("Show Path Optimization", toolParams.m_showOpt);
// nk_layout_row_dynamic(ctx, 20, 1); toolParams.m_showNeis = ImGui.RadioButton("Show Neighbours", toolParams.m_showNeis);
// toolParams.m_showNeis = nk_option_text(ctx, "Show Neighbours", toolParams.m_showNeis); ImGui.NewLine();
// nk_tree_state_pop(ctx);
// } ImGui.Text("Debug Draw");
// nk_layout_row_dynamic(ctx, 1, 1); ImGui.Separator();
// nk_spacing(ctx, 1); toolParams.m_showGrid = ImGui.RadioButton("Show Prox Grid", toolParams.m_showGrid);
// if (nk_tree_state_push(ctx, 0, "Debug Draw", toolParams.m_expandDebugDraw)) { toolParams.m_showNodes = ImGui.RadioButton("Show Nodes", toolParams.m_showNodes);
// nk_layout_row_dynamic(ctx, 20, 1); ImGui.Text($"Update Time: {crowdUpdateTime} ms");
// toolParams.m_showGrid = nk_option_text(ctx, "Show Prox Grid", toolParams.m_showGrid); }
// nk_layout_row_dynamic(ctx, 20, 1);
// toolParams.m_showNodes = nk_option_text(ctx, "Show Nodes", toolParams.m_showNodes);
// nk_tree_state_pop(ctx);
// }
// nk_layout_row_dynamic(ctx, 2, 1);
// nk_spacing(ctx, 1);
// nk_layout_row_dynamic(ctx, 18, 1);
// nk_label(ctx, string.format("Update Time: %d ms", crowdUpdateTime), NK_TEXT_ALIGN_LEFT);
// }
} }
private void updateAgentParams() private void updateAgentParams()