From 9b6e2ed51dd9dab5163907c77a83f8958d5a514b Mon Sep 17 00:00:00 2001 From: Roman <69218254+amzn-rhhong@users.noreply.github.com> Date: Wed, 17 Nov 2021 08:05:03 -0800 Subject: [PATCH] render solid skeleton option (#5610) * render solid skeleton option Signed-off-by: rhhong * Fix broken build Signed-off-by: rhhong * CR update Signed-off-by: rhhong --- .../Code/Source/AtomActorDebugDraw.cpp | 69 ++++++++++++++++++- .../Code/Source/AtomActorDebugDraw.h | 3 + .../Source/RenderPlugin/RenderOptions.cpp | 2 + 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.cpp index 89053f6349..698dd4cd75 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.cpp @@ -49,8 +49,14 @@ namespace AZ::Render RenderAABB(instance, renderActorSettings.m_staticAABBColor); } - // Render skeleton + // Render simple line skeleton if (renderFlags[EMotionFX::ActorRenderFlag::RENDER_LINESKELETON]) + { + RenderLineSkeleton(instance, renderActorSettings.m_lineSkeletonColor); + } + + // Render advance skeleton + if (renderFlags[EMotionFX::ActorRenderFlag::RENDER_SKELETON]) { RenderSkeleton(instance, renderActorSettings.m_skeletonColor); } @@ -110,6 +116,29 @@ namespace AZ::Render return aabbRadius * 0.01f; } + float AtomActorDebugDraw::CalculateBoneScale(EMotionFX::ActorInstance* actorInstance, EMotionFX::Node* node) + { + // Get the transform data + EMotionFX::TransformData* transformData = actorInstance->GetTransformData(); + const EMotionFX::Pose* pose = transformData->GetCurrentPose(); + + const size_t nodeIndex = node->GetNodeIndex(); + const size_t parentIndex = node->GetParentIndex(); + const AZ::Vector3 nodeWorldPos = pose->GetWorldSpaceTransform(nodeIndex).m_position; + + if (parentIndex != InvalidIndex) + { + const AZ::Vector3 parentWorldPos = pose->GetWorldSpaceTransform(parentIndex).m_position; + const AZ::Vector3 bone = parentWorldPos - nodeWorldPos; + const float boneLength = bone.GetLengthEstimate(); + + // 10% of the bone length is the sphere size + return boneLength * 0.1f; + } + + return 0.0f; + } + void AtomActorDebugDraw::PrepareForMesh(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM) { // Check if we have already prepared for the given mesh @@ -145,7 +174,7 @@ namespace AZ::Render auxGeom->DrawAabb(aabb, aabbColor, RPI::AuxGeomDraw::DrawStyle::Line); } - void AtomActorDebugDraw::RenderSkeleton(EMotionFX::ActorInstance* instance, const AZ::Color& skeletonColor) + void AtomActorDebugDraw::RenderLineSkeleton(EMotionFX::ActorInstance* instance, const AZ::Color& skeletonColor) { RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue(); @@ -189,6 +218,42 @@ namespace AZ::Render auxGeom->DrawLines(lineArgs); } + void AtomActorDebugDraw::RenderSkeleton(EMotionFX::ActorInstance* instance, const AZ::Color& skeletonColor) + { + RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue(); + + const EMotionFX::TransformData* transformData = instance->GetTransformData(); + const EMotionFX::Skeleton* skeleton = instance->GetActor()->GetSkeleton(); + const EMotionFX::Pose* pose = transformData->GetCurrentPose(); + const size_t numEnabled = instance->GetNumEnabledNodes(); + for (size_t i = 0; i < numEnabled; ++i) + { + EMotionFX::Node* joint = skeleton->GetNode(instance->GetEnabledNode(i)); + const size_t jointIndex = joint->GetNodeIndex(); + const size_t parentIndex = joint->GetParentIndex(); + + // check if this node has a parent and is a bone, if not skip it + if (parentIndex == InvalidIndex) + { + continue; + } + + const AZ::Vector3 nodeWorldPos = pose->GetWorldSpaceTransform(jointIndex).m_position; + const AZ::Vector3 parentWorldPos = pose->GetWorldSpaceTransform(parentIndex).m_position; + const AZ::Vector3 bone = parentWorldPos - nodeWorldPos; + const AZ::Vector3 boneDirection = bone.GetNormalizedEstimate(); + const AZ::Vector3 centerWorldPos = bone / 2 + nodeWorldPos; + const float boneLength = bone.GetLengthEstimate(); + const float boneScale = CalculateBoneScale(instance, joint); + const float parentBoneScale = CalculateBoneScale(instance, skeleton->GetNode(parentIndex)); + const float cylinderSize = boneLength - boneScale - parentBoneScale; + + // 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); + } + } + void AtomActorDebugDraw::RenderEMFXDebugDraw(EMotionFX::ActorInstance* instance) { RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue(); diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.h index 4178ad25f1..60db07cd8e 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorDebugDraw.h @@ -37,9 +37,12 @@ namespace AZ::Render private: + float CalculateBoneScale(EMotionFX::ActorInstance* actorInstance, EMotionFX::Node* node); float CalculateScaleMultiplier(EMotionFX::ActorInstance* instance) const; void PrepareForMesh(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM); + void RenderAABB(EMotionFX::ActorInstance* instance, const AZ::Color& aabbColor); + void RenderLineSkeleton(EMotionFX::ActorInstance* instance, const AZ::Color& skeletonColor); void RenderSkeleton(EMotionFX::ActorInstance* instance, const AZ::Color& skeletonColor); void RenderEMFXDebugDraw(EMotionFX::ActorInstance* instance); void RenderNormals( diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp index d1e3dc5ebc..3d1b0e3150 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderOptions.cpp @@ -545,6 +545,7 @@ namespace EMStudio ->Attribute(AZ::Edit::Attributes::ChangeNotify, &RenderOptions::OnLineSkeletonColorChangedCallback) ->DataElement(AZ::Edit::UIHandlers::Default, &RenderOptions::m_skeletonColor, "Solid skeleton color", "Solid skeleton color.") + ->Attribute(AZ_CRC("AlphaChannel", 0xa0cab5cf), true) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &RenderOptions::OnSkeletonColorChangedCallback) ->DataElement(AZ::Edit::UIHandlers::Default, &RenderOptions::m_selectionColor, "Selection gizmo color", "Selection gizmo color") @@ -1268,6 +1269,7 @@ namespace EMStudio void RenderOptions::OnSkeletonColorChangedCallback() const { PluginOptionsNotificationsBus::Event(s_skeletonColorOptionName, &PluginOptionsNotificationsBus::Events::OnOptionChanged, s_skeletonColorOptionName); + CopyToRenderActorSettings(EMotionFX::GetRenderActorSettings()); } void RenderOptions::OnSelectionColorChangedCallback() const