Hi,
I’m currently migrating a custom UsdImaging adapter from Hydra 1.0 to Hydra 2.0 API for a custom schema prim. This prim is visualized as HdBasisCurves. However, I keep encountering the following warning and am trying to understand what it implies:
// Warning: UsdImagingStageSceneIndex adapter invoked for UsdImagingDelegate for prim </transform1>, skipping...
There are not many examples out there but I think I have implemented everything correctly based on my current understanding":
So first, I created a custom data source to provide the point data:
constexpr const auto kSegmentsPerRing = 16;
constexpr const auto kNumRings = 1;
constexpr const auto kPointsPerSeg = 3; // cubic Bezier: p0, cp1, cp2
constexpr const auto kVertsPerRing = kSegmentsPerRing * kPointsPerSeg;
constexpr const auto kTotalPoints = kNumRings * kVertsPerRing;
constexpr const auto kRadius = 1.0f;
const auto kKappa = (4.0f / 3.0f) * std::tan(std::numbers::pi / (2.0f * kSegmentsPerRing));
class RingNodePointsDataSource : public HdTypedSampledDataSource
{
public:
HD_DECLARE_DATASOURCE(RingNodePointsDataSource);
PXR_NS::VtValue GetValue(HdSampledDataSource::Time shutterOffset) override {
return PXR_NS::VtValue(GetTypedValue(shutterOffset));
}
bool GetContributingSampleTimesForInterval(
HdSampledDataSource::Time startTime,
HdSampledDataSource::Time endTime,
std::vector<HdSampledDataSource::Time> *outSampleTimes) override
{
return false;
}
PXR_NS::VtVec3fArray GetTypedValue(HdSampledDataSource::Time shutterOffset) override
{
PXR_NS::VtVec3fArray points;
points.reserve(kTotalPoints);
...
return points;
}
};
My adapter then derives from UsdImagingSceneIndexPrimAdapter and implements all required functions.
In GetImagingSubprimData, I construct:
-
HdBasisCurves topology (cubic, bezier, periodic)
-
points primvar via my custom data source
class RingNodeAdapter : public PXR_NS::UsdImagingSceneIndexPrimAdapter
{
public:
using BaseAdapter = PXR_NS::UsdImagingSceneIndexPrimAdapter;
PXR_NS::TfTokenVector GetImagingSubprims(const PXR_NS::UsdPrim& prim) override;
PXR_NS::TfToken GetImagingSubprimType(const PXR_NS::UsdPrim& prim,
const PXR_NS::TfToken& subprim) override;
PXR_NS::HdContainerDataSourceHandle GetImagingSubprimData(
const PXR_NS::UsdPrim& prim,
const PXR_NS::TfToken& subprim,
const PXR_NS::UsdImagingDataSourceStageGlobals& stageGlobals) override;
PXR_NS::HdDataSourceLocatorSet InvalidateImagingSubprim(
const PXR_NS::UsdPrim& prim,
const PXR_NS::TfToken& subprim,
const PXR_NS::TfTokenVector& properties,
PXR_NS::UsdImagingPropertyInvalidationType invalidationType) override;
};
TfTokenVector
RingNodeAdapter::GetImagingSubprims(const UsdPrim& prim) {
return { TfToken() };
}
TfToken
RingNodeAdapter::GetImagingSubprimType(const UsdPrim& prim, const TfToken& subprim)
{
return HdPrimTypeTokens->basisCurves;
}
PXR_NS::HdContainerDataSourceHandle
RingNodeAdapter::GetImagingSubprimData(PXR_NS::UsdPrim const& prim,
PXR_NS::TfToken const& subprim,
const PXR_NS::UsdImagingDataSourceStageGlobals& stageGlobals)
{
// Build Topology
auto topologySource = PXR_NS::HdBasisCurvesTopologySchema::Builder()
.SetCurveVertexCounts(PXR_NS::HdRetainedTypedSampledDataSource<PXR_NS::VtIntArray>::New(
PXR_NS::VtIntArray(kNumRings, kVertsPerRing)))
.SetBasis(PXR_NS::HdRetainedTypedSampledDataSource<PXR_NS::TfToken>::New(PXR_NS::HdTokens->bezier))
.SetType(PXR_NS::HdRetainedTypedSampledDataSource<PXR_NS::TfToken>::New(PXR_NS::HdTokens->cubic))
.SetWrap(PXR_NS::HdRetainedTypedSampledDataSource<PXR_NS::TfToken>::New(PXR_NS::HdTokens->periodic))
.Build();
// Build Primvars using RingNodePointsDataSource
auto pointsPrimvar = PXR_NS::HdPrimvarSchema::Builder()
.SetPrimvarValue(RingNodePointsDataSource::New())
.SetInterpolation(PXR_NS::HdRetainedTypedSampledDataSource<PXR_NS::TfToken>::New(
PXR_NS::HdPrimvarSchemaTokens->vertex))
.SetRole(PXR_NS::HdRetainedTypedSampledDataSource<PXR_NS::TfToken>::New(
PXR_NS::HdPrimvarSchemaTokens->point))
.Build();
auto primvars = PXR_NS::HdRetainedContainerDataSource::New(
PXR_NS::HdPrimvarsSchemaTokens->points,
pointsPrimvar
);
PXR_NS::UsdTimeCode time(stageGlobals.GetTime());
PXR_NS::GfMatrix4d mat(1.0);
PXR_NS::UsdGeomXformable xformable(prim);
if (xformable) {
bool resetsXformStack = false;
xformable.GetLocalTransformation(&mat, &resetsXformStack, time);
}
return PXR_NS::HdRetainedContainerDataSource::New(
PXR_NS::HdBasisCurvesSchemaTokens->basisCurves,
PXR_NS::HdBasisCurvesSchema::Builder()
.SetTopology(topologySource)
.Build(),
PXR_NS::HdPrimvarsSchemaTokens->primvars,
primvars,
// XFORM
PXR_NS::HdXformSchemaTokens->xform,
PXR_NS::HdXformSchema::Builder()
.SetMatrix(
PXR_NS::HdRetainedTypedSampledDataSource<
PXR_NS::GfMatrix4d>::New(mat))
.Build(),
// VISIBILITY
PXR_NS::HdVisibilitySchemaTokens->visibility,
PXR_NS::HdVisibilitySchema::Builder()
.SetVisibility(
PXR_NS::HdRetainedTypedSampledDataSource<bool>::New(
PXR_NS::UsdGeomImageable(prim)
.ComputeVisibility(
PXR_NS::UsdTimeCode::Default())
!= PXR_NS::UsdGeomTokens->invisible))
.Build()
);
}
PXR_NS::HdDataSourceLocatorSet RingNodeAdapter::InvalidateImagingSubprim(
const PXR_NS::UsdPrim& prim,
const PXR_NS::TfToken& subprim,
const PXR_NS::TfTokenVector& properties,
PXR_NS::UsdImagingPropertyInvalidationType invalidationType)
{
PXR_NS::HdDataSourceLocatorSet locators;
for (const PXR_NS::TfToken& propertyName : properties) {
if (PXR_NS::UsdGeomXformable::IsTransformationAffectedByAttrNamed(propertyName)) {
locators.insert(PXR_NS::HdXformSchema::GetDefaultLocator());
} else if (propertyName == PXR_NS::UsdGeomTokens->visibility) {
locators.insert(PXR_NS::HdVisibilitySchema::GetDefaultLocator());
}
}
return locators;
}
I’ve registered the adapter as follows:
TF_REGISTRY_FUNCTION(TfType) {
TfType t = TfType::Define<RingNodeAdapter, TfType::Bases<RingNodeAdapter::BaseAdapter>>();
t.SetFactory<UsdImagingPrimAdapterFactory<RingNodeAdapter>>();
}
And in plugInfo.json:
"RingNodeAdapter": {
"bases": [
"UsdImagingSceneIndexPrimAdapter"
],
"primTypeName": "RingNode"
}
and here is a minimal usd example:
#usda 1.0
(
defaultPrim = "transform1"
)
def RingNode "transform1" (
)
{
}
Am I missing something required for Hydra 2.0 adapter registration? Is there an additional step that I am missing?
Any help is really appreciated.
-H
