Add joint selection visual support (#5860)

* Render joint orientation

Signed-off-by: rhhong <rhhong@amazon.com>

* joint selection will affect rendering result in emfx atom debug draw

Signed-off-by: rhhong <rhhong@amazon.com>

* Render line skeleton with joint selection

Signed-off-by: rhhong <rhhong@amazon.com>

* bug fix

Signed-off-by: rhhong <rhhong@amazon.com>

* fix build error

Signed-off-by: rhhong <rhhong@amazon.com>

* CR feedback - checking the actor instances for joint selection

Signed-off-by: rhhong <rhhong@amazon.com>
This commit is contained in:
Roman
2021-11-29 08:39:43 -08:00
committed by GitHub
parent ff631ac07c
commit c59f973900
6 changed files with 98 additions and 6 deletions
@@ -23,6 +23,7 @@
#include <EMotionFX/Source/TransformData.h>
#include <EMotionFX/Source/Mesh.h>
#include <EMotionFX/Source/Node.h>
#include <EMotionFX/Source/JointSelectionBus.h>
namespace AZ::Render
{
@@ -212,6 +213,13 @@ namespace AZ::Render
m_auxVertices.clear();
m_auxVertices.reserve(numJoints * 2);
m_auxColors.clear();
m_auxColors.reserve(numJoints * 2);
AZ::Color renderColor;
const AZStd::unordered_set<size_t>* cachedSelectedJointIndices;
EMotionFX::JointSelectionRequestBus::BroadcastResult(
cachedSelectedJointIndices, &EMotionFX::JointSelectionRequests::FindSelectedJointIndices, instance);
for (size_t jointIndex = 0; jointIndex < numJoints; ++jointIndex)
{
@@ -227,18 +235,29 @@ namespace AZ::Render
continue;
}
if (cachedSelectedJointIndices && cachedSelectedJointIndices->find(jointIndex) != cachedSelectedJointIndices->end())
{
renderColor = SelectedColor;
}
else
{
renderColor = skeletonColor;
}
const AZ::Vector3 parentPos = pose->GetWorldSpaceTransform(parentIndex).m_position;
m_auxVertices.emplace_back(parentPos);
m_auxColors.emplace_back(renderColor);
const AZ::Vector3 bonePos = pose->GetWorldSpaceTransform(jointIndex).m_position;
m_auxVertices.emplace_back(bonePos);
m_auxColors.emplace_back(renderColor);
}
RPI::AuxGeomDraw::AuxGeomDynamicDrawArguments lineArgs;
lineArgs.m_verts = m_auxVertices.data();
lineArgs.m_vertCount = static_cast<uint32_t>(m_auxVertices.size());
lineArgs.m_colors = &skeletonColor;
lineArgs.m_colorCount = 1;
lineArgs.m_colors = m_auxColors.data();
lineArgs.m_colorCount = lineArgs.m_vertCount;
lineArgs.m_depthTest = RPI::AuxGeomDraw::DepthTest::Off;
auxGeom->DrawLines(lineArgs);
}
@@ -251,6 +270,12 @@ namespace AZ::Render
const EMotionFX::Skeleton* skeleton = instance->GetActor()->GetSkeleton();
const EMotionFX::Pose* pose = transformData->GetCurrentPose();
const size_t numEnabled = instance->GetNumEnabledNodes();
AZ::Color renderColor = skeletonColor;
const AZStd::unordered_set<size_t>* cachedSelectedJointIndices;
EMotionFX::JointSelectionRequestBus::BroadcastResult(
cachedSelectedJointIndices, &EMotionFX::JointSelectionRequests::FindSelectedJointIndices, instance);
for (size_t i = 0; i < numEnabled; ++i)
{
EMotionFX::Node* joint = skeleton->GetNode(instance->GetEnabledNode(i));
@@ -273,9 +298,17 @@ namespace AZ::Render
const float parentBoneScale = CalculateBoneScale(instance, skeleton->GetNode(parentIndex));
const float cylinderSize = boneLength - boneScale - parentBoneScale;
if (cachedSelectedJointIndices && cachedSelectedJointIndices->find(jointIndex) != cachedSelectedJointIndices->end())
{
renderColor = SelectedColor;
}
else
{
renderColor = skeletonColor;
}
// Render the bone cylinder, the cylinder will be directed towards the node's parent and must fit between the spheres
auxGeom->DrawCylinder(centerWorldPos, boneDirection, boneScale, cylinderSize, skeletonColor);
auxGeom->DrawSphere(nodeWorldPos, boneScale, skeletonColor);
auxGeom->DrawCylinder(centerWorldPos, boneDirection, boneScale, cylinderSize, renderColor);
auxGeom->DrawSphere(nodeWorldPos, boneScale, renderColor);
}
}
@@ -597,6 +630,10 @@ namespace AZ::Render
return;
}
const AZStd::unordered_set<size_t>* cachedSelectedJointIndices;
EMotionFX::JointSelectionRequestBus::BroadcastResult(
cachedSelectedJointIndices, &EMotionFX::JointSelectionRequests::FindSelectedJointIndices, actorInstance);
const EMotionFX::Actor* actor = actorInstance->GetActor();
const EMotionFX::Skeleton* skeleton = actor->GetSkeleton();
const EMotionFX::TransformData* transformData = actorInstance->GetTransformData();
@@ -607,7 +644,6 @@ namespace AZ::Render
AzFramework::WindowSize viewportSize = viewportContext->GetViewportSize();
m_drawParams.m_position = AZ::Vector3(static_cast<float>(viewportSize.m_width), 0.0f, 1.0f) +
TopRightBorderPadding * viewportContext->GetDpiScalingFactor();
m_drawParams.m_color = jointNameColor;
m_drawParams.m_scale = AZ::Vector2(BaseFontSize);
m_drawParams.m_hAlign = AzFramework::TextHorizontalAlignment::Right;
m_drawParams.m_monospace = false;
@@ -624,6 +660,14 @@ namespace AZ::Render
const AZ::Vector3 worldPos = pose->GetWorldSpaceTransform(jointIndex).m_position;
m_drawParams.m_position = worldPos;
if (cachedSelectedJointIndices && cachedSelectedJointIndices->find(jointIndex) != cachedSelectedJointIndices->end())
{
m_drawParams.m_color = SelectedColor;
}
else
{
m_drawParams.m_color = jointNameColor;
}
m_fontDrawInterface->DrawScreenAlignedText3d(m_drawParams, joint->GetName());
}
}
@@ -640,6 +684,10 @@ namespace AZ::Render
const EMotionFX::Pose* pose = transformData->GetCurrentPose();
const float constPreScale = scale * unitScale * 3.0f;
const AZStd::unordered_set<size_t>* cachedSelectedJointIndices;
EMotionFX::JointSelectionRequestBus::BroadcastResult(
cachedSelectedJointIndices, &EMotionFX::JointSelectionRequests::FindSelectedJointIndices, actorInstance);
const size_t numEnabled = actorInstance->GetNumEnabledNodes();
for (size_t i = 0; i < numEnabled; ++i)
{
@@ -649,7 +697,12 @@ namespace AZ::Render
static const float axisBoneScale = 50.0f;
const float size = CalculateBoneScale(actorInstance, joint) * constPreScale * axisBoneScale;
AZ::Transform worldTM = pose->GetWorldSpaceTransform(jointIndex).ToAZTransform();
RenderLineAxis(debugDisplay, worldTM, size, false /*selected*/);
bool selected = false;
if (cachedSelectedJointIndices && cachedSelectedJointIndices->find(jointIndex) != cachedSelectedJointIndices->end())
{
selected = true;
}
RenderLineAxis(debugDisplay, worldTM, size, selected);
}
}
@@ -84,6 +84,7 @@ namespace AZ::Render
static constexpr float BaseFontSize = 0.7f;
const Vector3 TopRightBorderPadding = AZ::Vector3(-40.0f, 22.0f, 0.0f);
const AZ::Color SelectedColor = AZ::Color{ 1.0f, 0.67f, 0.0f, 1.0f };
RPI::AuxGeomFeatureProcessorInterface* m_auxGeomFeatureProcessor = nullptr;
AZStd::vector<AZ::Vector3> m_auxVertices;
@@ -0,0 +1,23 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/EBus/EBus.h>
#include <AzCore/std/containers/unordered_set.h>
namespace EMotionFX
{
class JointSelectionRequests
: public AZ::EBusTraits
{
public:
virtual const AZStd::unordered_set<size_t>* FindSelectedJointIndices(EMotionFX::ActorInstance* instance) const = 0;
};
using JointSelectionRequestBus = AZ::EBus<JointSelectionRequests>;
}
@@ -97,6 +97,7 @@ namespace EMStudio
m_compileDate = AZStd::string::format("%s", MCORE_DATE);
EMotionFX::SkeletonOutlinerNotificationBus::Handler::BusConnect();
EMotionFX::JointSelectionRequestBus::Handler::BusConnect();
// log some information
LogInfo();
@@ -107,6 +108,7 @@ namespace EMStudio
// destructor
EMStudioManager::~EMStudioManager()
{
EMotionFX::JointSelectionRequestBus::Handler::BusDisconnect();
EMotionFX::SkeletonOutlinerNotificationBus::Handler::BusDisconnect();
if (m_eventProcessingCallback)
@@ -19,6 +19,8 @@
// include the gizmos
#include <EMotionFX/Rendering/Common/TransformationManipulator.h>
#include <EMotionFX/Source/JointSelectionBus.h>
// include the EMStudio Config
#include "EMStudioConfig.h"
#include <MysticQt/Source/MysticQtManager.h>
@@ -52,6 +54,7 @@ namespace EMStudio
*/
class EMSTUDIO_API EMStudioManager
: private EMotionFX::SkeletonOutlinerNotificationBus::Handler
, private EMotionFX::JointSelectionRequestBus::Handler
{
public:
AZ_RTTI(EMStudio::EMStudioManager, "{D45E95CF-0C7B-44F1-A9D4-99A1E12A5AB5}")
@@ -103,6 +106,15 @@ namespace EMStudio
void SetSelectedJointIndices(const AZStd::unordered_set<size_t>& selectedJointIndices);
const AZStd::unordered_set<size_t>& GetSelectedJointIndices() const { return m_selectedJointIndices; }
const AZStd::unordered_set<size_t>* FindSelectedJointIndices(EMotionFX::ActorInstance* instance) const
{
if (instance == m_commandManager->GetCurrentSelection().GetSingleActorInstance())
{
return &m_selectedJointIndices;
}
return nullptr;
}
Workspace* GetWorkspace() { return &m_workspace; }
// functions for adding/removing gizmos
@@ -42,6 +42,7 @@ set(FILES
Source/EMotionFXManager.h
Source/EMotionFXAllocatorInitializer.cpp
Source/EMotionFXAllocatorInitializer.h
Source/JointSelectionBus.h
Source/KeyFrame.h
Source/KeyFrame.inl
Source/KeyFrameFinder.h