Added joint orientation rendering (#5821)
* Render joint orientation Signed-off-by: rhhong <rhhong@amazon.com> * fix build error Signed-off-by: rhhong <rhhong@amazon.com> * CR feedback Signed-off-by: rhhong <rhhong@amazon.com>
This commit is contained in:
@@ -6,6 +6,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
|
||||
|
||||
#include <AtomActorDebugDraw.h>
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
#include <Atom/RPI.Public/AuxGeom/AuxGeomDraw.h>
|
||||
@@ -25,6 +27,7 @@
|
||||
namespace AZ::Render
|
||||
{
|
||||
AtomActorDebugDraw::AtomActorDebugDraw(AZ::EntityId entityId)
|
||||
: m_entityId(entityId)
|
||||
{
|
||||
m_auxGeomFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity<RPI::AuxGeomFeatureProcessorInterface>(entityId);
|
||||
}
|
||||
@@ -42,9 +45,11 @@ namespace AZ::Render
|
||||
return;
|
||||
}
|
||||
|
||||
const RPI::Scene* scene = RPI::Scene::GetSceneForEntityId(instance->GetEntityId());
|
||||
const RPI::Scene* scene = RPI::Scene::GetSceneForEntityId(m_entityId);
|
||||
const RPI::ViewportContextPtr viewport = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get()->GetViewportContextByScene(scene);
|
||||
AzFramework::DebugDisplayRequests* debugDisplay = GetDebugDisplay(viewport->GetId());
|
||||
const AZ::Render::RenderActorSettings& renderActorSettings = EMotionFX::GetRenderActorSettings();
|
||||
const float scaleMultiplier = CalculateScaleMultiplier(instance);
|
||||
|
||||
// Render aabb
|
||||
if (renderFlags[EMotionFX::ActorRenderFlag::RENDER_AABB])
|
||||
@@ -75,6 +80,12 @@ namespace AZ::Render
|
||||
RenderEMFXDebugDraw(instance);
|
||||
}
|
||||
|
||||
// Render
|
||||
if (renderFlags[EMotionFX::ActorRenderFlag::RENDER_NODEORIENTATION])
|
||||
{
|
||||
RenderNodeOrientations(instance, debugDisplay, renderActorSettings.m_nodeOrientationScale * scaleMultiplier);
|
||||
}
|
||||
|
||||
// Render vertex normal, face normal, tagent and wireframe.
|
||||
const bool renderVertexNormals = renderFlags[EMotionFX::ActorRenderFlag::RENDER_VERTEXNORMALS];
|
||||
const bool renderFaceNormals = renderFlags[EMotionFX::ActorRenderFlag::RENDER_FACENORMALS];
|
||||
@@ -87,7 +98,6 @@ namespace AZ::Render
|
||||
const EMotionFX::Pose* pose = instance->GetTransformData()->GetCurrentPose();
|
||||
const size_t geomLODLevel = instance->GetLODLevel();
|
||||
const size_t numEnabled = instance->GetNumEnabledNodes();
|
||||
const float scaleMultiplier = CalculateScaleMultiplier(instance);
|
||||
for (size_t i = 0; i < numEnabled; ++i)
|
||||
{
|
||||
EMotionFX::Node* node = instance->GetActor()->GetSkeleton()->GetNode(instance->GetEnabledNode(i));
|
||||
@@ -175,6 +185,13 @@ namespace AZ::Render
|
||||
}
|
||||
}
|
||||
|
||||
AzFramework::DebugDisplayRequests* AtomActorDebugDraw::GetDebugDisplay(AzFramework::ViewportId viewportId)
|
||||
{
|
||||
AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus;
|
||||
AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, viewportId);
|
||||
return AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus);
|
||||
}
|
||||
|
||||
void AtomActorDebugDraw::RenderAABB(EMotionFX::ActorInstance* instance, const AZ::Color& aabbColor)
|
||||
{
|
||||
RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue();
|
||||
@@ -610,4 +627,89 @@ namespace AZ::Render
|
||||
m_fontDrawInterface->DrawScreenAlignedText3d(m_drawParams, joint->GetName());
|
||||
}
|
||||
}
|
||||
|
||||
void AtomActorDebugDraw::RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance,
|
||||
AzFramework::DebugDisplayRequests* debugDisplay, float scale)
|
||||
{
|
||||
// Get the actor and the transform data
|
||||
const float unitScale =
|
||||
1.0f / (float)MCore::Distance::ConvertValue(1.0f, MCore::Distance::UNITTYPE_METERS, EMotionFX::GetEMotionFX().GetUnitType());
|
||||
const EMotionFX::Actor* actor = actorInstance->GetActor();
|
||||
const EMotionFX::Skeleton* skeleton = actor->GetSkeleton();
|
||||
const EMotionFX::TransformData* transformData = actorInstance->GetTransformData();
|
||||
const EMotionFX::Pose* pose = transformData->GetCurrentPose();
|
||||
const float constPreScale = scale * unitScale * 3.0f;
|
||||
|
||||
const size_t numEnabled = actorInstance->GetNumEnabledNodes();
|
||||
for (size_t i = 0; i < numEnabled; ++i)
|
||||
{
|
||||
EMotionFX::Node* joint = skeleton->GetNode(actorInstance->GetEnabledNode(i));
|
||||
const size_t jointIndex = joint->GetNodeIndex();
|
||||
|
||||
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*/);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomActorDebugDraw::RenderLineAxis(
|
||||
AzFramework::DebugDisplayRequests* debugDisplay,
|
||||
AZ::Transform worldTM,
|
||||
float size,
|
||||
bool selected,
|
||||
bool renderAxisName)
|
||||
{
|
||||
const float axisHeight = size * 0.7f;
|
||||
const float frontSize = size * 5.0f + 0.2f;
|
||||
const AZ::Vector3 position = worldTM.GetTranslation();
|
||||
|
||||
// Render x axis
|
||||
{
|
||||
AZ::Color xSelectedColor = selected ? AZ::Colors::Orange : AZ::Colors::Red;
|
||||
|
||||
const AZ::Vector3 xAxisDir = (worldTM.TransformPoint(AZ::Vector3(size, 0.0f, 0.0f)) - position).GetNormalized();
|
||||
const AZ::Vector3 xAxisArrowStart = position + xAxisDir * axisHeight;
|
||||
debugDisplay->SetColor(xSelectedColor);
|
||||
debugDisplay->DrawArrow(position, xAxisArrowStart, size);
|
||||
|
||||
if (renderAxisName)
|
||||
{
|
||||
const AZ::Vector3 xNamePos = position + xAxisDir * (size * 1.15f);
|
||||
debugDisplay->DrawTextLabel(xNamePos, frontSize, "X");
|
||||
}
|
||||
}
|
||||
|
||||
// Render y axis
|
||||
{
|
||||
AZ::Color ySelectedColor = selected ? AZ::Colors::Orange : AZ::Colors::Blue;
|
||||
|
||||
const AZ::Vector3 yAxisDir = (worldTM.TransformPoint(AZ::Vector3(0.0f, size, 0.0f)) - position).GetNormalized();
|
||||
const AZ::Vector3 yAxisArrowStart = position + yAxisDir * axisHeight;
|
||||
debugDisplay->SetColor(ySelectedColor);
|
||||
debugDisplay->DrawArrow(position, yAxisArrowStart, size);
|
||||
|
||||
if (renderAxisName)
|
||||
{
|
||||
const AZ::Vector3 yNamePos = position + yAxisDir * (size * 1.15f);
|
||||
debugDisplay->DrawTextLabel(yNamePos, frontSize, "Y");
|
||||
}
|
||||
}
|
||||
|
||||
// Render z axis
|
||||
{
|
||||
AZ::Color zSelectedColor = selected ? AZ::Colors::Orange : AZ::Colors::Green;
|
||||
|
||||
const AZ::Vector3 zAxisDir = (worldTM.TransformPoint(AZ::Vector3(0.0f, 0.0f, size)) - position).GetNormalized();
|
||||
const AZ::Vector3 zAxisArrowStart = position + zAxisDir * axisHeight;
|
||||
debugDisplay->SetColor(zSelectedColor);
|
||||
debugDisplay->DrawArrow(position, zAxisArrowStart, size);
|
||||
|
||||
if (renderAxisName)
|
||||
{
|
||||
const AZ::Vector3 zNamePos = position + zAxisDir * (size * 1.15f);
|
||||
debugDisplay->DrawTextLabel(zNamePos, frontSize, "Z");
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace AZ::Render
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
#include <Integration/Rendering/RenderActorInstance.h>
|
||||
#include <Atom/RPI.Public/ViewportContext.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class DebugDisplayRequests;
|
||||
}
|
||||
|
||||
namespace EMotionFX
|
||||
{
|
||||
class Mesh;
|
||||
@@ -42,6 +47,7 @@ namespace AZ::Render
|
||||
float CalculateBoneScale(EMotionFX::ActorInstance* actorInstance, EMotionFX::Node* node);
|
||||
float CalculateScaleMultiplier(EMotionFX::ActorInstance* instance) const;
|
||||
void PrepareForMesh(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM);
|
||||
AzFramework::DebugDisplayRequests* GetDebugDisplay(AzFramework::ViewportId viewportId);
|
||||
|
||||
void RenderAABB(EMotionFX::ActorInstance* instance, const AZ::Color& aabbColor);
|
||||
void RenderLineSkeleton(EMotionFX::ActorInstance* instance, const AZ::Color& skeletonColor);
|
||||
@@ -63,11 +69,18 @@ namespace AZ::Render
|
||||
void RenderWireframe(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM, float wireframeScale, float scaleMultiplier,
|
||||
const AZ::Color& wireframeColor);
|
||||
void RenderJointNames(EMotionFX::ActorInstance* actorInstance, RPI::ViewportContextPtr viewportContext, const AZ::Color& jointNameColor);
|
||||
void RenderNodeOrientations(EMotionFX::ActorInstance* actorInstance, AzFramework::DebugDisplayRequests* debugDisplay, float scale = 1.0f);
|
||||
void RenderLineAxis(
|
||||
AzFramework::DebugDisplayRequests* debugDisplay,
|
||||
AZ::Transform worldTM, //!< The world space transformation matrix to visualize. */
|
||||
float size, //!< The size value in units is used to control the scaling of the axis. */
|
||||
bool selected, //!< Set to true if you want to render the axis using the selection color. */
|
||||
bool renderAxisName = false);
|
||||
|
||||
EMotionFX::Mesh* m_currentMesh = nullptr; /**< A pointer to the mesh whose world space positions are in the pre-calculated positions buffer.
|
||||
NULL in case we haven't pre-calculated any positions yet. */
|
||||
AZStd::vector<AZ::Vector3> m_worldSpacePositions; /**< The buffer used to store world space positions for rendering normals
|
||||
tangents and the wireframe. */
|
||||
EMotionFX::Mesh* m_currentMesh = nullptr; //!< A pointer to the mesh whose world space positions are in the pre-calculated positions buffer.
|
||||
//!< NULL in case we haven't pre-calculated any positions yet.
|
||||
AZStd::vector<AZ::Vector3> m_worldSpacePositions; //!< The buffer used to store world space positions for rendering normals
|
||||
//!< tangents and the wireframe.
|
||||
|
||||
static constexpr float BaseFontSize = 0.7f;
|
||||
const Vector3 TopRightBorderPadding = AZ::Vector3(-40.0f, 22.0f, 0.0f);
|
||||
@@ -75,6 +88,7 @@ namespace AZ::Render
|
||||
RPI::AuxGeomFeatureProcessorInterface* m_auxGeomFeatureProcessor = nullptr;
|
||||
AZStd::vector<AZ::Vector3> m_auxVertices;
|
||||
AZStd::vector<AZ::Color> m_auxColors;
|
||||
EntityId m_entityId;
|
||||
|
||||
AzFramework::TextDrawParameters m_drawParams;
|
||||
AzFramework::FontDrawInterface* m_fontDrawInterface = nullptr;
|
||||
|
||||
@@ -46,8 +46,8 @@ namespace EMStudio
|
||||
CreateViewOptionEntry(contextMenu, "Line Skeleton", EMotionFX::ActorRenderFlag::RENDER_LINESKELETON);
|
||||
CreateViewOptionEntry(contextMenu, "Solid Skeleton", EMotionFX::ActorRenderFlag::RENDER_SKELETON);
|
||||
CreateViewOptionEntry(contextMenu, "Joint Names", EMotionFX::ActorRenderFlag::RENDER_NODENAMES);
|
||||
CreateViewOptionEntry(contextMenu, "Joint Orientations", EMotionFX::ActorRenderFlag::RENDER_NODEORIENTATION);
|
||||
// [EMFX-TODO] Add those option once implemented.
|
||||
// CreateViewOptionEntry(contextMenu, "Joint Orientations", EMotionFX::ActorRenderFlag::RENDER_NODEORIENTATION);
|
||||
// CreateViewOptionEntry(contextMenu, "Actor Bind Pose", EMotionFX::ActorRenderFlag::RENDER_ACTORBINDPOSE);
|
||||
contextMenu->addSeparator();
|
||||
CreateViewOptionEntry(contextMenu, "Hit Detection Colliders", EMotionFX::ActorRenderFlag::RENDER_HITDETECTION_COLLIDERS);
|
||||
|
||||
+2
@@ -1063,6 +1063,7 @@ namespace EMStudio
|
||||
settings.m_vertexNormalsScale = m_vertexNormalsScale;
|
||||
settings.m_faceNormalsScale = m_faceNormalsScale;
|
||||
settings.m_tangentsScale = m_tangentsScale;
|
||||
settings.m_nodeOrientationScale = m_nodeOrientationScale;
|
||||
|
||||
settings.m_vertexNormalsColor = m_vertexNormalsColor;
|
||||
settings.m_faceNormalsColor = m_faceNormalsColor;
|
||||
@@ -1112,6 +1113,7 @@ namespace EMStudio
|
||||
void RenderOptions::OnNodeOrientationScaleChangedCallback() const
|
||||
{
|
||||
PluginOptionsNotificationsBus::Event(s_nodeOrientationScaleOptionName, &PluginOptionsNotificationsBus::Events::OnOptionChanged, s_nodeOrientationScaleOptionName);
|
||||
CopyToRenderActorSettings(EMotionFX::GetRenderActorSettings());
|
||||
}
|
||||
|
||||
void RenderOptions::OnScaleBonesOnLengthChangedCallback() const
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace AZ::Render
|
||||
float m_faceNormalsScale = 1.0f;
|
||||
float m_tangentsScale = 1.0f;
|
||||
float m_wireframeScale = 1.0f;
|
||||
float m_nodeOrientationScale = 1.0f;
|
||||
|
||||
AZ::Color m_hitDetectionColliderColor{0.44f, 0.44f, 0.44f, 1.0f};
|
||||
AZ::Color m_selectedHitDetectionColliderColor{ 0.3f, 0.56f, 0.88f, 1.0f };
|
||||
|
||||
Reference in New Issue
Block a user