Skip to content

Commit

Permalink
USD Viewer: reworked up axis transform handling
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMostDiligent committed Dec 3, 2023
1 parent cb6f7ea commit a46eeb4
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 36 deletions.
95 changes: 60 additions & 35 deletions Samples/USDViewer/src/USDViewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "HnTokens.hpp"
#include "HnCamera.hpp"
#include "HnLight.hpp"
#include "GfTypeConversions.hpp"

#include "imgui.h"
#include "ImGuiUtils.hpp"
Expand Down Expand Up @@ -109,9 +110,6 @@ void USDViewer::Initialize(const SampleInitInfo& InitInfo)
m_pImmediateContext->TransitionResourceStates(_countof(Barriers), Barriers);

m_Camera.SetDistRange(0.1, 10000);
m_Camera.SetDefaultRotation(-PI_F / 3.f, PI_F / 6.f);
m_Camera.ResetDefaults();
m_Camera.SetExtraRotation(QuaternionF::RotationFromAxisAngle(float3{0.75, 0.0, 0.75}, PI_F));

m_PostProcessParams.ToneMappingMode = TONE_MAPPING_MODE_UNCHARTED2;
m_PostProcessParams.ConvertOutputToSRGB = m_ConvertPSOutputToGamma;
Expand Down Expand Up @@ -154,53 +152,48 @@ BoundBox USDViewer::ComputeSceneBounds(const pxr::UsdPrim& Prim) const
return BB;
}

float4x4 USDViewer::ComputeStageTransform()
static float4x4 GetUpAxisTransform(const pxr::TfToken UpAxis)
{
float4x4 Transform = float4x4::Identity();
if (BoundBox SceneBB = ComputeSceneBounds(m_Stage.Stage->GetPseudoRoot()))
{
float CameraDist = 0;
for (size_t i = 0; i < 8; ++i)
{
float3 BBCorner = {
(i & 0x1) ? SceneBB.Max.x : SceneBB.Min.x,
(i & 0x2) ? SceneBB.Max.y : SceneBB.Min.y,
(i & 0x4) ? SceneBB.Max.z : SceneBB.Min.z,
};
CameraDist = std::max(CameraDist, length(BBCorner));
}
m_Camera.SetDist(CameraDist * 2.f);
}

const pxr::TfToken UpAxis = pxr::UsdGeomGetStageUpAxis(m_Stage.Stage);
// NOTE: transform must not contain reflection as otherwise
// rotation in TRS widget will work incorrectly.
if (UpAxis == pxr::UsdGeomTokens->x)
{
Transform *= Diligent::float4x4{
return float4x4{
// clang-format off
0, -1, 0, 0,
-1, 0, 0, 0,
0, 0, 1, 0,
0, 0, -1, 0,
0, 0, 0, 1
// clang-format on
};
}
else if (UpAxis == pxr::UsdGeomTokens->y)
{
Transform *= float4x4::Scale(1, -1, 1);
return float4x4{
// clang-format off
1, 0, 0, 0,
0, -1, 0, 0,
0, 0, -1, 0,
0, 0, 0, 1
// clang-format on
};
}
else if (UpAxis == pxr::UsdGeomTokens->z)
{
Transform *= Diligent::float4x4{
return float4x4{
// clang-format off
1, 0, 0, 0,
-1, 0, 0, 0,
0, 0, -1, 0,
0, -1, 0, 0,
0, 0, 0, 1
// clang-format on
};
}

return Transform;
else
{
LOG_WARNING_MESSAGE("Unknown up axis '", UpAxis, "'. Using identity transform");
return float4x4::Identity();
}
}

void USDViewer::LoadStage()
Expand Down Expand Up @@ -264,15 +257,47 @@ void USDViewer::LoadStage()
m_Stage.TaskManager->SetFrameParams(m_FrameParams);

m_RenderParams.SelectedPrimId = {};
m_RenderParams.Transform = ComputeStageTransform();
m_Stage.TaskManager->SetRenderRprimParams(m_RenderParams);

m_PostProcessParams = {};
m_Stage.TaskManager->SetPostProcessParams(m_PostProcessParams);

const pxr::TfToken UpAxis = pxr::UsdGeomGetStageUpAxis(m_Stage.Stage);
m_Stage.RootTransform = GetUpAxisTransform(UpAxis);
m_Stage.ImagingDelegate->SetRootTransform(USD::ToGfMatrix4d(m_Stage.RootTransform));

float SceneExtent = 100;
if (BoundBox SceneBB = ComputeSceneBounds(m_Stage.Stage->GetPseudoRoot()))
{
SceneExtent = 0;
for (size_t i = 0; i < 8; ++i)
{
float3 BBCorner = {
(i & 0x1) ? SceneBB.Max.x : SceneBB.Min.x,
(i & 0x2) ? SceneBB.Max.y : SceneBB.Min.y,
(i & 0x4) ? SceneBB.Max.z : SceneBB.Min.z,
};
SceneExtent = std::max(SceneExtent, length(BBCorner));
}
m_Camera.SetDist(SceneExtent * 2.f);
}

USD::HnRenderAxesTaskParams RenderAxesParams;
RenderAxesParams.Transform = float4x4::Scale(300) * m_RenderParams.Transform;
RenderAxesParams.Transform = float4x4::Scale(SceneExtent * 2.f) * m_Stage.RootTransform;
m_Stage.TaskManager->SetRenderAxesParams(RenderAxesParams);

if (UpAxis == pxr::UsdGeomTokens->x)
{
m_Camera.SetRotation(PI_F / 4.f, PI_F / 6.f);
}
else if (UpAxis == pxr::UsdGeomTokens->y)
{
m_Camera.SetRotation(-PI_F / 4.f, PI_F / 6.f);
}
else if (UpAxis == pxr::UsdGeomTokens->z)
{
m_Camera.SetRotation(PI_F * 3.f / 4.f, PI_F / 6.f);
}
}

// Render a frame
Expand Down Expand Up @@ -373,7 +398,7 @@ void USDViewer::EditSelectePrimTransform()
pxr::GfMatrix4d ParentGlobalXForm = GetPrimGlobalTransform(Prim.GetParent());
float4x4 ParentGlobalMatrix = float4x4::MakeMatrix(ParentGlobalXForm.data());

ParentGlobalMatrix = ParentGlobalMatrix * m_RenderParams.Transform;
ParentGlobalMatrix = ParentGlobalMatrix * m_Stage.RootTransform;

pxr::GfMatrix4d LocalXform = pxr::GfMatrix4d{1.0};
bool ResetsXformStack = false;
Expand All @@ -383,9 +408,9 @@ void USDViewer::EditSelectePrimTransform()

ImGuiIO& io = ImGui::GetIO();
ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y);
ImGuizmo::OPERATION mCurrentGizmoOperation = ImGuizmo::UNIVERSAL;
ImGuizmo::MODE mCurrentGizmoMode = ImGuizmo::LOCAL;
if (ImGuizmo::Manipulate(m_CameraView.Data(), m_CameraProj.Data(), mCurrentGizmoOperation, mCurrentGizmoMode, NewGlobalMatrix.Data(), NULL, NULL))
ImGuizmo::OPERATION GizmoOperation = static_cast<ImGuizmo::OPERATION>(static_cast<int>(ImGuizmo::UNIVERSAL) & ~static_cast<int>(ImGuizmo::ROTATE_SCREEN));
ImGuizmo::MODE GizmoMode = ImGuizmo::LOCAL;
if (ImGuizmo::Manipulate(m_CameraView.Data(), m_CameraProj.Data(), GizmoOperation, GizmoMode, NewGlobalMatrix.Data(), NULL, NULL))
{
Diligent::float4x4 NewLocalMatrix = NewGlobalMatrix * ParentGlobalMatrix.Inverse();
XFormable.MakeMatrixXform().Set(pxr::GfMatrix4d{
Expand Down Expand Up @@ -673,7 +698,7 @@ void USDViewer::Update(double CurrTime, double ElapsedTime)
m_Camera.SetZoomSpeed(m_Camera.GetDist() * 0.1f);
m_Camera.Update(m_InputController);
auto CameraDist = m_Camera.GetDist();
m_CameraView = m_Camera.GetRotation().ToMatrix() * float4x4::Translation(0.f, 0.0f, CameraDist);
m_CameraView = float4x4::Scale(1, -1, 1) * m_Camera.GetRotation().ToMatrix() * float4x4::Translation(0, 0, CameraDist);
// Apply pretransform matrix that rotates the scene according the surface orientation
m_CameraView *= GetSurfacePretransformMatrix(float3{0, 0, 1});

Expand Down
3 changes: 2 additions & 1 deletion Samples/USDViewer/src/USDViewer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ class USDViewer final : public SampleBase
void SetSelectedPrim(const pxr::SdfPath& SelectedPrimId);
void EditSelectePrimTransform();

float4x4 ComputeStageTransform();
BoundBox ComputeSceneBounds(const pxr::UsdPrim& Prim) const;

private:
Expand All @@ -97,6 +96,8 @@ class USDViewer final : public SampleBase

pxr::SdfPath SelectedPrimId;

float4x4 RootTransform = float4x4::Identity();

explicit operator bool() const
{
return Stage && RenderDelegate && RenderIndex && ImagingDelegate && TaskManager;
Expand Down

0 comments on commit a46eeb4

Please sign in to comment.