Motion Matching: Debug visualization improvements

* Moved reposibility from the instance to the system component to render debug visualizations. Why? To make sure all motion extraction deltas got applied to the character already and avoid any mismatches between last and current frame (resulting in visual jittering).
* Added frame database stats to the ImGui monitor.
* Switched ImGuiMonitor from internal histogram group to the now shared version in LYImGuiUtils.
* Added a new debug draw bus that the motion matching instance hooks to, so that the system component can control when to render debug visualizations.
* Added class description for the motion matching instance.

Signed-off-by: Benjamin Jillich <jillich@amazon.com>
This commit is contained in:
Benjamin Jillich
2022-02-04 16:29:27 +01:00
parent 80ac118893
commit 1a23dc7b93
9 changed files with 153 additions and 186 deletions
@@ -16,10 +16,11 @@ namespace EMotionFX::MotionMatching
ImGuiMonitor::ImGuiMonitor()
{
m_performanceStats.m_name = "Performance Statistics";
m_performanceStats.SetName("Performance Statistics");
m_performanceStats.SetHistogramBinCount(500);
m_featureCosts.m_name = "Feature Costs";
m_featureCosts.m_histogramContainerCount = 100;
m_featureCosts.SetName("Feature Costs");
m_featureCosts.SetHistogramBinCount(100);
ImGui::ImGuiUpdateListenerBus::Handler::BusConnect();
ImGuiMonitorRequestBus::Handler::BusConnect();
@@ -40,18 +41,40 @@ namespace EMotionFX::MotionMatching
if (ImGui::Begin("Motion Matching"))
{
if (ImGui::CollapsingHeader("Motion Database", ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed))
{
if (ImGui::BeginTable("MDB", 2))
{
ImGui::TableNextColumn(); ImGui::Text("Memory Usage: %.2f MB", m_frameDatabaseInfo.m_memoryUsedInBytes / 1024.0f / 1024.0f);
ImGui::TableNextColumn(); ImGui::Text("Motion Data: %.0f minutes", m_frameDatabaseInfo.m_motionDataInSeconds / 60.0f);
ImGui::TableNextColumn(); ImGui::Text("Num Frames: %zu", m_frameDatabaseInfo.m_numFrames);
ImGui::TableNextColumn(); ImGui::Text("Num Motions: %zu", m_frameDatabaseInfo.m_numMotions);
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("Feature Matrix", ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed))
{
ImGui::Text("Memory Usage: %.2f MB", m_featureMatrixMemoryUsageInBytes / 1024.0f / 1024.0f);
ImGui::Text("Num Frames: %zu", m_featureMatrixNumFrames);
ImGui::Text("Num Feature Components: %zu", m_featureMatrixNumComponents);
if (ImGui::BeginTable("FM", 2))
{
ImGui::TableNextColumn(); ImGui::Text("Memory Usage: %.2f MB", m_featurMatrixInfo.m_memoryUsedInBytes / 1024.0f / 1024.0f);
ImGui::TableNextColumn();
ImGui::TableNextColumn(); ImGui::Text("Num Frames: %zu", m_featurMatrixInfo.m_numFrames);
ImGui::TableNextColumn(); ImGui::Text("Num Feature Components: %zu", m_featurMatrixInfo.m_numDimensions);
ImGui::EndTable();
}
}
if (ImGui::CollapsingHeader("Kd-Tree", ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed))
{
ImGui::Text("Memory Usage: %.2f MB", m_kdTreeMemoryUsageInBytes / 1024.0f / 1024.0f);
ImGui::Text("Num Nodes: %zu", m_kdTreeNumNodes);
ImGui::Text("Num Dimensions: %zu", m_kdTreeNumDimensions);
if (ImGui::BeginTable("KDT", 2))
{
ImGui::TableNextColumn(); ImGui::Text("Memory Usage: %.2f MB", m_kdTreeInfo.m_memoryUsedInBytes / 1024.0f / 1024.0f);
ImGui::TableNextColumn();
ImGui::TableNextColumn(); ImGui::Text("Num Nodes: %zu", m_kdTreeInfo.m_numNodes);
ImGui::TableNextColumn(); ImGui::Text("Num Dimensions: %zu", m_kdTreeInfo.m_numDimensions);
ImGui::EndTable();
}
}
m_performanceStats.OnImGuiUpdate();
@@ -63,8 +86,8 @@ namespace EMotionFX::MotionMatching
{
if (ImGui::BeginMenu("Motion Matching"))
{
ImGui::MenuItem(m_performanceStats.m_name.c_str(), "", &m_performanceStats.m_show);
ImGui::MenuItem(m_featureCosts.m_name.c_str(), "", &m_featureCosts.m_show);
ImGui::MenuItem(m_performanceStats.GetName(), "", &m_performanceStats.m_show);
ImGui::MenuItem(m_featureCosts.GetName(), "", &m_featureCosts.m_show);
ImGui::EndMenu();
}
}
@@ -78,67 +101,6 @@ namespace EMotionFX::MotionMatching
{
m_featureCosts.PushHistogramValue(costName, value, color);
}
void ImGuiMonitor::HistogramGroup::PushHistogramValue(const char* valueName, float value, const AZ::Color& color)
{
auto iterator = m_histogramIndexByName.find(valueName);
if (iterator != m_histogramIndexByName.end())
{
ImGui::LYImGuiUtils::HistogramContainer& histogramContiner = m_histograms[iterator->second];
histogramContiner.PushValue(value);
histogramContiner.SetBarLineColor(ImColor(color.GetR(), color.GetG(), color.GetB(), color.GetA()));
}
else
{
ImGui::LYImGuiUtils::HistogramContainer newHistogram;
newHistogram.Init(/*histogramName=*/valueName,
/*containerCount=*/m_histogramContainerCount,
/*viewType=*/ImGui::LYImGuiUtils::HistogramContainer::ViewType::Histogram,
/*displayOverlays=*/true,
/*min=*/0.0f,
/*max=*/0.0f);
newHistogram.SetMoveDirection(ImGui::LYImGuiUtils::HistogramContainer::PushRightMoveLeft);
newHistogram.PushValue(value);
m_histogramIndexByName[valueName] = m_histograms.size();
m_histograms.push_back(newHistogram);
}
}
void ImGuiMonitor::HistogramGroup::OnImGuiUpdate()
{
if (!m_show)
{
return;
}
if (ImGui::CollapsingHeader(m_name.c_str(), ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed))
{
for (auto& histogram : m_histograms)
{
ImGui::BeginGroup();
{
histogram.Draw(ImGui::GetColumnWidth() - 70, s_histogramHeight);
ImGui::SameLine();
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(0,0,0,255));
{
const ImColor color = histogram.GetBarLineColor();
ImGui::PushStyleColor(ImGuiCol_Button, color.Value);
{
const AZStd::string valueString = AZStd::string::format("%.2f", histogram.GetLastValue());
ImGui::Button(valueString.c_str());
}
ImGui::PopStyleColor();
}
ImGui::PopStyleColor();
}
ImGui::EndGroup();
}
}
}
} // namespace EMotionFX::MotionMatching
#endif // IMGUI_ENABLED