#include "CreatePrimCommand.h" #include "../../utils/Logger.h" #include #include #include #include namespace UsdLayerManager { // --------------------------------------------------------------------------- // ApplyCameraDefaultOrientation // // USD cameras always use +Y-up / look-down-−Z in their own local frame. // For a Y-up stage that is already the standard world forward direction, so // the identity transform is fine. // // For a Z-up stage the identity transform would point the camera straight // DOWN (world −Z = −up), which produces wrong orientation when the viewport // switches to the prim, and wrong tumble/roll directions when navigating. // // Fix: rotate the camera +90° around its local X axis so that: // camera local +Y (up) → world +Z (stage up axis) ✓ // camera local −Z (view) → world +Y (horizontal "forward") ✓ // --------------------------------------------------------------------------- static void ApplyCameraDefaultOrientation(pxr::UsdPrim& prim, pxr::UsdStageRefPtr stage) { if (!prim.IsValid() || !stage) return; bool isZUp = (pxr::UsdGeomGetStageUpAxis(stage) == pxr::UsdGeomTokens->z); if (!isZUp) return; // Y-up default (identity) is already correct pxr::UsdGeomXformCommonAPI xformAPI(prim); // +90° around X: camera up aligns with world Z, view direction becomes +Y xformAPI.SetRotate(pxr::GfVec3f(90.f, 0.f, 0.f), pxr::UsdGeomXformCommonAPI::RotationOrderXYZ, pxr::UsdTimeCode::Default()); } CreatePrimCommand::CreatePrimCommand(pxr::UsdStageRefPtr stage, const pxr::SdfPath& primPath, const pxr::TfToken& typeName) : m_stage(stage) , m_primPath(primPath) , m_typeName(typeName) , m_description("Create " + typeName.GetString() + " " + primPath.GetString()) { } void CreatePrimCommand::Execute() { if (!m_stage) return; try { pxr::UsdPrim prim = m_stage->DefinePrim(m_primPath, m_typeName); if (!prim.IsValid()) { LOG_ERROR("CreatePrimCommand: failed to define prim " + m_primPath.GetString()); return; } // Camera-specific initialisation: orient the prim so the camera looks // in the correct "forward" direction for the stage's up-axis. if (m_typeName == pxr::TfToken("Camera")) ApplyCameraDefaultOrientation(prim, m_stage); } catch (const std::exception& e) { LOG_ERROR(std::string("CreatePrimCommand::Execute error: ") + e.what()); } } void CreatePrimCommand::Undo() { if (!m_stage) return; try { if (!m_stage->RemovePrim(m_primPath)) LOG_ERROR("CreatePrimCommand: failed to remove prim " + m_primPath.GetString()); } catch (const std::exception& e) { LOG_ERROR(std::string("CreatePrimCommand::Undo error: ") + e.what()); } } } // namespace UsdLayerManager