Files
UsdLayerManager/src/core/commands/CreatePrimCommand.cpp
T
2026-06-06 09:34:39 +08:00

80 lines
3.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "CreatePrimCommand.h"
#include "../../utils/Logger.h"
#include <pxr/usd/usd/prim.h>
#include <pxr/usd/usdGeom/xformCommonAPI.h>
#include <pxr/usd/usdGeom/metrics.h>
#include <pxr/usd/usdGeom/tokens.h>
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