Hi,
I’m fairly new to USD so apologize in advance if I use the wrong terminology. I’m investigating how hard it would be to write a Generative Procedural plugin to generate hair from our custom hair tool at work.
The Procedural Mesh Generation topic was really helpful to get me started. I based my plugin on the _CubePerMeshPointProcedural example in the source of USD. Here is a stripped out version of the code I have:
class _CurveHdGpProcedural final: public HdGpGenerativeProcedural
{
public:
//…
auto Update(
const HdSceneIndexBaseRefPtr& inputScene,
const ChildPrimTypeMap& previousResult,
const DependencyMap& dirtiedDependencies,
HdSceneIndexObserver::DirtiedPrimEntries* outputDirtiedPrims)
-> ChildPrimTypeMap override
{
ChildPrimTypeMap result;
// Populate m_num_vertices, m_indices etc
// …
// Tell GetChildPrim() to generate the schema
m_load_data = true;
const SdfPath path = _GetProceduralPrimPath();
const SdfPath curves_path = path.AppendChild(TfToken("Curves"));
result[curves_path] = HdPrimTypeTokens->basisCurves;
if (outputDirtiedPrims)
{
outputDirtiedPrims->emplace_back(
curves_path,
HdBasisCurvesSchema::GetDefaultLocator());
}
return result;
}
// Returns dataSource of a child prim
auto GetChildPrim(
const HdSceneIndexBaseRefPtr& inputScene,
const SdfPath& childPrimPath) -> HdSceneIndexPrim override
{
HdSceneIndexPrim result;
if (m_load_data)
{
result.primType = HdPrimTypeTokens->basisCurves;
result.dataSource = HdRetainedContainerDataSource::New(
HdBasisCurvesSchemaTokens->basisCurves,
getCurvesTopology(),
HdPrimvarsSchemaTokens->primvars,
getCurvesPrimvars());
m_load_data = false;
}
return result;
}
private:
auto getCurvesTopology() const -> HdContainerDataSourceHandle
{
using _IntArrayDataSource
= HdRetainedTypedSampledDataSource<VtIntArray>;
using _TokenDataSource = HdRetainedTypedSampledDataSource<TfToken>;
static const _IntArrayDataSource::Handle vertex_count_data_source
= _IntArrayDataSource::New(m_num_vertices);
static const _IntArrayDataSource::Handle indices_data_source
= _IntArrayDataSource::New(m_indices);
static const _TokenDataSource::Handle basis_data_source
= _TokenDataSource::New(HdTokens->catmullRom);
static const _TokenDataSource::Handle type_data_source
= _TokenDataSource::New(HdTokens->linear);
static const _TokenDataSource::Handle wrap_data_source
= _TokenDataSource::New(HdTokens->nonperiodic);
static const HdContainerDataSourceHandle curves_data_source
= HdBasisCurvesSchema::Builder()
.SetTopology(
HdBasisCurvesTopologySchema::Builder()
.SetCurveVertexCounts(vertex_count_data_source)
.SetCurveIndices(indices_data_source)
.SetBasis(basis_data_source)
.SetType(type_data_source)
.SetWrap(wrap_data_source)
.Build())
.Build();
return curves_data_source;
}
auto getCurvesPrimvars() const -> HdContainerDataSourceHandle
{
using _PointDataSource
= HdRetainedTypedSampledDataSource<VtVec3fArray>;
using _FloatDataSource
= HdRetainedTypedSampledDataSource<VtFloatArray>;
static const HdContainerDataSourceHandle primvars_data_source
= HdRetainedContainerDataSource::New(
HdPrimvarsSchemaTokens->points,
HdPrimvarSchema::Builder()
.SetPrimvarValue(_PointDataSource::New(m_points))
.SetInterpolation(
HdPrimvarSchema::BuildInterpolationDataSource(
HdPrimvarSchemaTokens->uniform))
.SetRole(HdPrimvarSchema::BuildRoleDataSource(
HdPrimvarSchemaTokens->point))
.Build(),
HdPrimvarsSchemaTokens->widths,
HdPrimvarSchema::Builder()
.SetPrimvarValue(_FloatDataSource::New(m_widths))
.SetInterpolation(
HdPrimvarSchema::BuildInterpolationDataSource(
HdPrimvarSchemaTokens->uniform))
.Build());
return primvars_data_source;
}
private: // Member variables
bool m_load_data = true;
VtIntArray m_num_vertices;
VtIntArray m_indices;
VtVec3fArray m_points;
VtFloatArray m_widths;
};
I can draw a box with my plugin if I switch to using HdMeshSchema
, construct it similar to what they do in _CubePerMeshPointProcedural::_GetChildMeshDs()
and _CubePerMeshPointProcedural::_GetChildPrimvarsDs
. So I know I got the plugin hooked up correctly.
I don’t get any errors when running this with HdBasisCurvesSchema
. My suspicion is that I missing something when building the schema for the curves. As I can get similar behavior if removing the HdPrimvarSchema::BuildInterpolationDataSource
when testing with a mesh.
I have tested to just to hard code a basic curve for testing in case something is wrong with how I read in the data form the hair tool:
VtIntArray m_num_vertices{4};
VtIntArray m_indices{0, 1, 2, 3};
VtVec3fArray m_points{
{0.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{0.0, 2.0, 0.0},
{0.0, 3.0, 0.0},
};
VtFloatArray m_widths{0.1, 0.2, 0.2, 0.2};
Same issue.
Setting TF_DEBUG="*"
doesn’t give any clues either.
Anyone know what I’m doing wrong/missing?
Thanks.