Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
#include <pxr/usdImaging/usdImaging/usdRenderProductSchema.h>
#include <pxr/usdImaging/usdImaging/usdRenderSettingsSchema.h>

#include <ufeExtensions/Global.h>
#include <ufe/pathString.h>

#include <algorithm>
#include <string>

Expand All @@ -38,17 +41,44 @@ const TfToken kExternalCameraToken("adskUsd:externalCamera");
// ExternalCameraResolvingSceneIndex.
const SdfPath kExternalCameraPrefix("/__adskUsd__externalCamera");

// Sentinel SdfPath component used to preserve UFE multi-segment paths (Maya
// DAG path ',' USD path) when storing external camera paths in Hydra.
const std::string kUfeSegmentSentinel("__ufeSegment__");

// External camera paths are either through USD (already uses '/' as a
// separator), or through Maya (uses '|' as a separator, converted to '/' for
// SdfPath representation). We also erase the UFE path segment ',' separator.
// SdfPath representation). We also replace the UFE path segment ',' separator with
// kUfeSegmentSentinel followed by UFE runTimeId.
// ex: |stage1|stageShape1,/camera1
// -> /__adskUsd__externalCamera/stage1/stageShape1/__ufeSegment__<runTimeId>/camera1
SdfPath SanitizeExternalPath(const std::string& rawValue)
Comment thread
benyoon-adsk marked this conversation as resolved.
Outdated
{
std::string pathStr = rawValue;
std::string mayaPath = rawValue;
std::string extCamPath;
Ufe::Rtid rtId;

const auto commaPos = rawValue.find(',');
if (commaPos != std::string::npos) {
Ufe::Path ufePath = Ufe::PathString::path(rawValue);
rtId = ufePath.getSegments()
.back()
.runTimeId(); // runTimeId() returns the last segment's runTimeId.
mayaPath = rawValue.substr(0, commaPos);
extCamPath = rawValue.substr(commaPos + 1);
}

std::replace(pathStr.begin(), pathStr.end(), '|', '/');
pathStr.erase(std::remove(pathStr.begin(), pathStr.end(), ','), pathStr.end());
std::replace(mayaPath.begin(), mayaPath.end(), '|', '/');

SdfPath sanitizedPath = SdfPath(mayaPath).MakeRelativePath(SdfPath::AbsoluteRootPath());
if (!extCamPath.empty()) {
const std::string sentinelAndRtId
= kUfeSegmentSentinel + std::to_string(static_cast<unsigned int>(rtId));
sanitizedPath = sanitizedPath.AppendChild(TfToken(sentinelAndRtId));
sanitizedPath = sanitizedPath.AppendPath(
SdfPath(extCamPath).MakeRelativePath(SdfPath::AbsoluteRootPath()));
}

return kExternalCameraPrefix.AppendPath(SdfPath(pathStr).MakeRelativePath(SdfPath::AbsoluteRootPath()));
return kExternalCameraPrefix.AppendPath(sanitizedPath);
Comment thread
ppt-adsk marked this conversation as resolved.
Outdated
}

} // anonymous namespace
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ typedef PXR_NS::TfRefPtr<const MhExternalCameraOverrideSceneIndex>
/// A filtering scene index that overrides the camera data source on
/// renderSettings and renderProduct prims when an adskUsd:externalCamera key
/// is present in their namespacedSettings. The external camera path is
/// sanitized ('|' -> '/', ',' stripped) and prefixed with
/// "/__adskUsd__externalCamera" before being written into the camera field.
/// sanitized ('|' -> '/', ',' replaced with __ufeSegment__<runTimeId>) and prefixed
/// with "/__adskUsd__externalCamera" before being written into the camera field.
///
class MhExternalCameraOverrideSceneIndex
: public PXR_NS::HdSingleInputFilteringSceneIndexBase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ using namespace UfeExtensions;
namespace {

const TfToken kExternalCameraComponent("__adskUsd__externalCamera");
const std::string kUfeSegmentSentinel("__ufeSegment__");

Ufe::PathSegment MayaAppPathToUfePathSegment(const SdfPath& mayaAppPath)
{
Ufe::PathSegment::Components components;
components.push_back(Ufe::PathComponent("world"));
for (const SdfPath& prefix : mayaAppPath.GetPrefixes()) {
if (!prefix.IsAbsoluteRootPath()) {
Comment thread
ppt-adsk marked this conversation as resolved.
Outdated
components.push_back(prefix.GetNameToken().GetString());
}
}
return Ufe::PathSegment(std::move(components), getMayaRunTimeId(), '|');
}

SdfPath ResolveExternalCameraPath(const SdfPath& inputPath)
{
Expand Down Expand Up @@ -91,12 +104,28 @@ SdfPath ResolveExternalCameraPath(const SdfPath& inputPath)
// multiple reader behavior), which has been considered in the past, but
// this requires UFE versus Maya TBB configuration management.

Ufe::PathSegment::Components components;
components.push_back(Ufe::PathComponent("world"));
Ufe::Path appUfePath;
SdfPath mayaAppPath;
SdfPath extCamPath;
Ufe::Rtid rtId;
for (const SdfPath& prefix : appPath.GetPrefixes()) {
components.push_back(prefix.GetNameToken().GetString());
const std::string& name = prefix.GetNameToken().GetString();
if (TfStringStartsWith(name, kUfeSegmentSentinel)) {
const std::string rtIdStr = name.substr(kUfeSegmentSentinel.size());
rtId = static_cast<Ufe::Rtid>(std::stoul(rtIdStr));
mayaAppPath = prefix.GetParentPath();
extCamPath = appPath.ReplacePrefix(prefix, SdfPath::AbsoluteRootPath());
break; // We assume only 2 segments.
}
}

if (!extCamPath.IsEmpty() && rtId) {
appUfePath = Ufe::Path(Ufe::Path::Segments {
MayaAppPathToUfePathSegment(mayaAppPath),
sdfPathToUfePathSegment(extCamPath, rtId) });
} else {
appUfePath = Ufe::Path(MayaAppPathToUfePathSegment(appPath));
}
Ufe::Path appUfePath(Ufe::PathSegment(components, getMayaRunTimeId(), '|'));
Comment thread
ppt-adsk marked this conversation as resolved.
auto hydraPath = Fvp::ufePathToPrimSelections(appUfePath);

// Camera is non-instanced, so there will be a single PrimSelection.
Expand Down
31 changes: 31 additions & 0 deletions test/lib/cmdLineRender/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ mayaHydra_add_cmd_line_render_test(${scene}
RENDERED_IMAGE_SUBDIR projects/default/images
RENDERED_IMAGE_NAME ${sceneFileNameNoExt}
RENDERER HdStormRendererPlugin
TEST_NAME_SUFFIX Storm
Comment thread
ppt-adsk marked this conversation as resolved.
RENDERER_ARGS "-x 960 -y 540 -cam \"|camera1\" -rd ../images -im ${sceneFileNameNoExt}"
)

Expand All @@ -129,9 +130,39 @@ mayaHydra_add_cmd_line_render_test(${scene}
RENDERED_IMAGE_SUBDIR projects/default/images
RENDERED_IMAGE_NAME ${sceneFileNameNoExt}
RENDERER HdStormRendererPlugin
TEST_NAME_SUFFIX Storm
RENDERER_ARGS "-x 960 -y 540 -cam \"|stage1|stageShape1,/camera1\" -rd ../images -im ${sceneFileNameNoExt}"
)

# Test -cam with USD camera in HdArnold.
set(scene basic/usdCamera.ma)
cmake_path(GET scene STEM sceneFileNameNoExt)
mayaHydra_add_cmd_line_render_test(${scene}
COPY_SCENE
RENDERED_IMAGE_SUBDIR projects/default/images
RENDERED_IMAGE_NAME ${sceneFileNameNoExt}
RENDERER HdArnoldRendererPlugin
TEST_NAME_SUFFIX Arnold
RENDERER_ARGS "-x 960 -y 540 -cam \"|stage1|stageShape1,/camera1\" -rd ../images -im ${sceneFileNameNoExt}"
)

# Test the same as above but with Hydra V2 render settings.
set(scene basic/usdCamera.ma)
set(render_dir ${CMAKE_BINARY_DIR}/test/Temporary/${sceneFileNameNoExt}_Arnold_v2_rs/projects/default/images)
cmake_path(GET scene STEM sceneFileNameNoExt)
mayaHydra_add_cmd_line_render_test(${scene}
COPY_SCENE
RENDERER HdArnoldRendererPlugin
RENDERED_IMAGE_SUBDIR projects/default/images
RENDERED_IMAGE_NAME ${sceneFileNameNoExt}_Arnold_v2_rs
RENDERER_ARGS "-x 960 -y 540 -cam \"|stage1|stageShape1,/camera1\" -rd \"${render_dir}\" -im ${sceneFileNameNoExt}_Arnold_v2_rs"
TEST_NAME_SUFFIX Arnold_v2_rs
ENV
"MAYA_HYDRA_HD_ARNOLD_HYDRA_V2_RENDER_SETTINGS=1"
"USDIMAGINGGL_ENGINE_ENABLE_SCENE_INDEX=1"
"TF_DEBUG=MAYAHYDRAPLUGIN_BATCHRENDER_RENDER_SETTINGS"
Comment thread
ppt-adsk marked this conversation as resolved.
)

# Use a small vertical resolution to avoid the Arnold watermark.
mayaHydra_add_cmd_line_render_test(renderSettings/arnoldResolution.ma
COPY_SCENE
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading