Skip to content

Commit 1600a5a

Browse files
authored
HYDRA-2414 : Fix external camera resolution for two-segment UFE paths (#474)
1 parent 57f5bf8 commit 1600a5a

8 files changed

Lines changed: 70 additions & 13 deletions

File tree

lib/mayaHydra/hydraExtensions/sceneIndex/mhExternalCameraOverrideSceneIndex.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,35 @@ const TfToken kExternalCameraToken("adskUsd:externalCamera");
3838
// ExternalCameraResolvingSceneIndex.
3939
const SdfPath kExternalCameraPrefix("/__adskUsd__externalCamera");
4040

41+
// Sentinel SdfPath component used to preserve UFE multi-segment paths (Maya
42+
// DAG path ',' USD path) when storing external camera paths in Hydra.
43+
const std::string kUfeSegmentSentinel("__ufeSegment__");
44+
4145
// External camera paths are either through USD (already uses '/' as a
4246
// separator), or through Maya (uses '|' as a separator, converted to '/' for
43-
// SdfPath representation). We also erase the UFE path segment ',' separator.
44-
SdfPath SanitizeExternalPath(const std::string& rawValue)
47+
// SdfPath representation). We also replace the UFE path segment ',' separator with
48+
// kUfeSegmentSentinel followed by UFE runTimeId.
49+
// ex: |stage1|stageShape1,/camera1
50+
// -> /__adskUsd__externalCamera/stage1/stageShape1__ufeSegment__/camera1
51+
// Note: For now, we assume the second segment is a USD path.
52+
// This may not always be the case, the second segment could be a path from a custom plugin.
53+
// Need to handle this case in the future.
54+
SdfPath SanitizeExternalPath(const std::string& ufePathStr)
4555
{
46-
std::string pathStr = rawValue;
56+
const auto segmentEnd = ufePathStr.find(',');
4757

58+
// Maya path: replace '|' with '/'
59+
auto pathStr = ufePathStr.substr(0, segmentEnd);
4860
std::replace(pathStr.begin(), pathStr.end(), '|', '/');
49-
pathStr.erase(std::remove(pathStr.begin(), pathStr.end(), ','), pathStr.end());
5061

51-
return kExternalCameraPrefix.AppendPath(SdfPath(pathStr).MakeRelativePath(SdfPath::AbsoluteRootPath()));
62+
if (segmentEnd != std::string::npos) {
63+
// Assume the second segment is a USD path, and already has '/' path
64+
// component separator. Append segment separator sentinel and USD path.
65+
pathStr += kUfeSegmentSentinel + ufePathStr.substr(segmentEnd + 1);
66+
}
67+
68+
return kExternalCameraPrefix.AppendPath(
69+
SdfPath(pathStr).MakeRelativePath(SdfPath::AbsoluteRootPath()));
5270
}
5371

5472
} // anonymous namespace

lib/mayaHydra/hydraExtensions/sceneIndex/mhExternalCameraOverrideSceneIndex.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ typedef PXR_NS::TfRefPtr<const MhExternalCameraOverrideSceneIndex>
3939
/// A filtering scene index that overrides the camera data source on
4040
/// renderSettings and renderProduct prims when an adskUsd:externalCamera key
4141
/// is present in their namespacedSettings. The external camera path is
42-
/// sanitized ('|' -> '/', ',' stripped) and prefixed with
43-
/// "/__adskUsd__externalCamera" before being written into the camera field.
42+
/// sanitized ('|' -> '/', ',' replaced with __ufeSegment__) and prefixed
43+
/// with "/__adskUsd__externalCamera" before being written into the camera field.
4444
///
4545
class MhExternalCameraOverrideSceneIndex
4646
: public PXR_NS::HdSingleInputFilteringSceneIndexBase

lib/mayaHydra/hydraExtensions/sceneIndex/mhExternalCameraResolvingSceneIndex.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@
2828
#include <pxr/imaging/hd/tokens.h>
2929
#include <pxr/usd/sdf/path.h>
3030

31-
#include <ufe/path.h>
31+
#include <ufe/pathString.h>
3232

3333
PXR_NAMESPACE_USING_DIRECTIVE
3434
using namespace UfeExtensions;
3535

3636
namespace {
3737

3838
const TfToken kExternalCameraComponent("__adskUsd__externalCamera");
39+
const std::string kUfeSegmentSentinel("__ufeSegment__");
3940

4041
SdfPath ResolveExternalCameraPath(const SdfPath& inputPath)
4142
{
@@ -91,12 +92,19 @@ SdfPath ResolveExternalCameraPath(const SdfPath& inputPath)
9192
// multiple reader behavior), which has been considered in the past, but
9293
// this requires UFE versus Maya TBB configuration management.
9394

94-
Ufe::PathSegment::Components components;
95-
components.push_back(Ufe::PathComponent("world"));
96-
for (const SdfPath& prefix : appPath.GetPrefixes()) {
97-
components.push_back(prefix.GetNameToken().GetString());
95+
const auto appPathStr = appPath.GetString();
96+
const auto segmentEnd = appPathStr.find(kUfeSegmentSentinel);
97+
98+
// Maya path: replace '/' with '|'
99+
auto pathStr = appPathStr.substr(0, segmentEnd);
100+
std::replace(pathStr.begin(), pathStr.end(), '/', '|');
101+
102+
if (segmentEnd != std::string::npos) {
103+
// Assume the second segment is a USD path, and already has '/' path
104+
// component separator. Remove segment separator sentinel.
105+
pathStr += "," + appPathStr.substr(segmentEnd + kUfeSegmentSentinel.length());
98106
}
99-
Ufe::Path appUfePath(Ufe::PathSegment(components, getMayaRunTimeId(), '|'));
107+
auto appUfePath = Ufe::PathString::path(pathStr);
100108
auto hydraPath = Fvp::ufePathToPrimSelections(appUfePath);
101109

102110
// Camera is non-instanced, so there will be a single PrimSelection.

test/lib/cmdLineRender/CMakeLists.txt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ mayaHydra_add_cmd_line_render_test(${scene}
117117
RENDERED_IMAGE_SUBDIR projects/default/images
118118
RENDERED_IMAGE_NAME ${sceneFileNameNoExt}
119119
RENDERER HdStormRendererPlugin
120+
TEST_NAME_SUFFIX Storm
120121
RENDERER_ARGS "-x 960 -y 540 -cam \"|camera1\" -rd ../images -im ${sceneFileNameNoExt}"
121122
)
122123

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

137+
# Test -cam with USD camera in HdArnold.
138+
set(scene basic/usdCamera.ma)
139+
cmake_path(GET scene STEM sceneFileNameNoExt)
140+
mayaHydra_add_cmd_line_render_test(${scene}
141+
COPY_SCENE
142+
RENDERED_IMAGE_SUBDIR projects/default/images
143+
RENDERED_IMAGE_NAME ${sceneFileNameNoExt}
144+
RENDERER HdArnoldRendererPlugin
145+
TEST_NAME_SUFFIX Arnold
146+
RENDERER_ARGS "-x 960 -y 540 -cam \"|stage1|stageShape1,/camera1\" -rd ../images -im ${sceneFileNameNoExt}"
147+
)
148+
149+
# Test the same as above but with Hydra V2 render settings.
150+
set(scene basic/usdCamera.ma)
151+
set(render_dir ${CMAKE_BINARY_DIR}/test/Temporary/${sceneFileNameNoExt}_Arnold_v2_rs/projects/default/images)
152+
cmake_path(GET scene STEM sceneFileNameNoExt)
153+
mayaHydra_add_cmd_line_render_test(${scene}
154+
COPY_SCENE
155+
RENDERER HdArnoldRendererPlugin
156+
RENDERED_IMAGE_SUBDIR projects/default/images
157+
RENDERED_IMAGE_NAME ${sceneFileNameNoExt}_Arnold_v2_rs
158+
RENDERER_ARGS "-x 960 -y 540 -cam \"|stage1|stageShape1,/camera1\" -rd \"${render_dir}\" -im ${sceneFileNameNoExt}_Arnold_v2_rs"
159+
TEST_NAME_SUFFIX Arnold_v2_rs
160+
ENV
161+
"MAYA_HYDRA_HD_ARNOLD_HYDRA_V2_RENDER_SETTINGS=1"
162+
"USDIMAGINGGL_ENGINE_ENABLE_SCENE_INDEX=1"
163+
"TF_DEBUG=MAYAHYDRAPLUGIN_BATCHRENDER_RENDER_SETTINGS"
164+
)
165+
135166
# Use a small vertical resolution to avoid the Arnold watermark.
136167
mayaHydra_add_cmd_line_render_test(renderSettings/arnoldResolution.ma
137168
COPY_SCENE
File renamed without changes.
58.7 KB
Loading
61.7 KB
Loading
File renamed without changes.

0 commit comments

Comments
 (0)