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:
@@ -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>;
|
||||
}
|
||||
+2
@@ -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)
|
||||
|
||||
+12
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user