Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
163 changes: 115 additions & 48 deletions pxr/imaging/hdSt/mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1269,10 +1269,7 @@ HdStMesh::_PopulateVertexPrimvars(HdSceneDelegate *sceneDelegate,
_topology->GetGeomSubsets().size());
primvars.insert(primvars.end(), varyingPvs.begin(), varyingPvs.end());

HdExtComputationPrimvarDescriptorVector compPrimvars =
sceneDelegate->GetExtComputationPrimvarDescriptors(id,
HdInterpolationVertex);

HdExtComputationPrimvarDescriptorVector compPrimvars;
HdBufferSourceSharedPtrVector sources;
HdBufferSourceSharedPtrVector reserveOnlySources;
HdBufferSourceSharedPtrVector separateComputationSources;
Expand Down Expand Up @@ -1312,50 +1309,73 @@ HdStMesh::_PopulateVertexPrimvars(HdSceneDelegate *sceneDelegate,
// and optimize if necessary.
//

HdSt_GetExtComputationPrimvarsComputations(
id,
sceneDelegate,
compPrimvars,
*dirtyBits,
&sources,
&reserveOnlySources,
&separateComputationSources,
&computations);

bool isPointsComputedPrimvar = false;
{
// Update tracked state for points and normals that are computed.
for (HdBufferSourceSharedPtrVector const& computedSources :
{reserveOnlySources, sources}) {
for (HdBufferSourceSharedPtr const& source: computedSources) {
if (source->GetName() == HdTokens->points) {
isPointsComputedPrimvar = true;
_pointsDataType = source->GetTupleType().type;
}
if (source->GetName() == HdTokens->normals) {
_sceneNormalsInterpolation = HdInterpolationVertex;
_sceneNormals = true;
}
}
}
}

bool isNormalsComputedPrimvar = false;
const bool doRefine = (refineLevel > 0);
const bool doQuadrangulate = _UseQuadIndices(renderIndex, _topology);

{
for (HdBufferSourceSharedPtr const & source : reserveOnlySources) {
_RefineOrQuadrangulateVertexAndVaryingPrimvar(
source, _topology, id, doRefine, doQuadrangulate,
resourceRegistry,
&computations, HdSt_MeshTopology::INTERPOLATE_VERTEX);
for (HdInterpolation interpolation : {HdInterpolationVertex, HdInterpolationVarying}) {
HdBufferSourceSharedPtrVector localSources;
HdBufferSourceSharedPtrVector localReserveOnlySources;
HdBufferSourceSharedPtrVector localSeparateComputationSources;
HdStComputationComputeQueuePairVector localComputations;

HdExtComputationPrimvarDescriptorVector localCompPrimvars =
sceneDelegate->GetExtComputationPrimvarDescriptors(id,
interpolation);

HdSt_GetExtComputationPrimvarsComputations(
id,
sceneDelegate,
localCompPrimvars,
*dirtyBits,
&localSources,
&localReserveOnlySources,
&localSeparateComputationSources,
&localComputations);
sources.insert(sources.end(), localSources.begin(), localSources.end());
reserveOnlySources.insert(reserveOnlySources.end(), localReserveOnlySources.begin(),
localReserveOnlySources.end());
separateComputationSources.insert(separateComputationSources.end(),
localSeparateComputationSources.begin(), localSeparateComputationSources.end());
computations.insert(computations.end(), localComputations.begin(), localComputations.end());
compPrimvars.insert(compPrimvars.end(), localCompPrimvars.begin(), localCompPrimvars.end());

{
// Update tracked state for points and normals that are computed.
for (HdBufferSourceSharedPtrVector const& computedSources :
{localReserveOnlySources, localSources}) {
for (HdBufferSourceSharedPtr const& source: computedSources) {
if (source->GetName() == HdTokens->points) {
isPointsComputedPrimvar = true;
_pointsDataType = source->GetTupleType().type;
}
if (source->GetName() == HdTokens->normals) {
isNormalsComputedPrimvar = true;
_sceneNormalsInterpolation = interpolation;
_sceneNormals = true;
}
}
}
}

{
const HdSt_MeshTopology::Interpolation hdStInterpolation =
interpolation == HdInterpolationVertex ?
HdSt_MeshTopology::INTERPOLATE_VERTEX :
HdSt_MeshTopology::INTERPOLATE_VARYING;
for (HdBufferSourceSharedPtr const & source : localReserveOnlySources) {
_RefineOrQuadrangulateVertexAndVaryingPrimvar(
source, _topology, id, doRefine, doQuadrangulate,
resourceRegistry,
&localComputations, hdStInterpolation);
}

for (HdBufferSourceSharedPtr const & source : sources) {
_RefineOrQuadrangulateVertexAndVaryingPrimvar(
source, _topology, id, doRefine, doQuadrangulate,
resourceRegistry,
&computations, HdSt_MeshTopology::INTERPOLATE_VERTEX);
for (HdBufferSourceSharedPtr const & source : localSources) {
_RefineOrQuadrangulateVertexAndVaryingPrimvar(
source, _topology, id, doRefine, doQuadrangulate,
resourceRegistry,
&localComputations, hdStInterpolation);
}
}
}

Expand Down Expand Up @@ -1436,6 +1456,12 @@ HdStMesh::_PopulateVertexPrimvars(HdSceneDelegate *sceneDelegate,
}

if (source->GetName() == HdTokens->normals) {
if (!TF_VERIFY(!isNormalsComputedPrimvar)) {
HF_VALIDATION_WARN(id,
"'normals' specified as both computed and authored "
"primvar. Skipping authored value.");
continue;
}
_sceneNormalsInterpolation =
isVarying ? HdInterpolationVarying : HdInterpolationVertex;
_sceneNormals = true;
Expand Down Expand Up @@ -1770,11 +1796,10 @@ HdStMesh::_PopulateFaceVaryingPrimvars(HdSceneDelegate *sceneDelegate,
HdStGetPrimvarDescriptors(this, drawItem, sceneDelegate,
HdInterpolationFaceVarying, repr, desc.geomStyle,
geomSubsetDescIndex, _topology->GetGeomSubsets().size());
if (primvars.empty() &&
!drawItem->GetFaceVaryingPrimvarRange())
{
return;
}

HdExtComputationPrimvarDescriptorVector compPrimvars =
sceneDelegate->GetExtComputationPrimvarDescriptors(id,
HdInterpolationFaceVarying);

HdStResourceRegistrySharedPtr const& resourceRegistry =
std::static_pointer_cast<HdStResourceRegistry>(
Expand Down Expand Up @@ -1807,6 +1832,35 @@ HdStMesh::_PopulateFaceVaryingPrimvars(HdSceneDelegate *sceneDelegate,
// these, or if they need to be converted to floats.
const bool doublesSupported = _GetDoubleSupport(resourceRegistry);


HdBufferSourceSharedPtrVector reserveOnlySources;
HdBufferSourceSharedPtrVector separateComputationSources;

HdSt_GetExtComputationPrimvarsComputations(
id,
sceneDelegate,
compPrimvars,
*dirtyBits,
&sources,
&reserveOnlySources,
&separateComputationSources,
&computations);

bool isNormalsComputedPrimvar = false;
{
// Update tracked state for normals that are computed.
for (HdBufferSourceSharedPtrVector const& computedSources :
{reserveOnlySources, sources}) {
for (HdBufferSourceSharedPtr const& source: computedSources) {
if (source->GetName() == HdTokens->normals) {
isNormalsComputedPrimvar = true;
_sceneNormalsInterpolation = HdInterpolationFaceVarying;
_sceneNormals = true;
}
}
}
}

for (HdPrimvarDescriptor const& primvar: primvars) {
if (!HdChangeTracker::IsPrimvarDirty(*dirtyBits, id, primvar.name)) {
continue;
Expand Down Expand Up @@ -1846,6 +1900,12 @@ HdStMesh::_PopulateFaceVaryingPrimvars(HdSceneDelegate *sceneDelegate,
}

if (source->GetName() == HdTokens->normals) {
if (!TF_VERIFY(!isNormalsComputedPrimvar)) {
HF_VALIDATION_WARN(id,
"'normals' specified as both computed and authored "
"primvar. Skipping authored value.");
continue;
}
_sceneNormalsInterpolation = HdInterpolationFaceVarying;
_sceneNormals = true;
} else if (source->GetName() == HdTokens->displayOpacity) {
Expand Down Expand Up @@ -1901,6 +1961,7 @@ HdStMesh::_PopulateFaceVaryingPrimvars(HdSceneDelegate *sceneDelegate,

HdBufferSpecVector bufferSpecs;
HdBufferSpec::GetBufferSpecs(sources, &bufferSpecs);
HdBufferSpec::GetBufferSpecs(reserveOnlySources, &bufferSpecs);
HdStGetBufferSpecsFromCompuations(computations, &bufferSpecs);

HdBufferArrayRangeSharedPtr range =
Expand Down Expand Up @@ -1935,6 +1996,12 @@ HdStMesh::_PopulateFaceVaryingPrimvars(HdSceneDelegate *sceneDelegate,
resourceRegistry->AddComputation(
drawItem->GetFaceVaryingPrimvarRange(), comp, queue);
}

if (!separateComputationSources.empty()) {
for (auto const& src : separateComputationSources) {
resourceRegistry->AddSource(src);
}
}
}

void
Expand Down
67 changes: 67 additions & 0 deletions pxr/usd/usdSkel/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2168,6 +2168,41 @@ _SkinFaceVaryingNormals(const TfToken& skinningMethod,
}


template <typename Matrix3>
bool
_SkinFaceVaryingNormals(const TfToken& skinningMethod,
const Matrix3& geomBindTransform,
TfSpan<const Matrix3> jointXforms,
TfSpan<const GfVec2f> influences,
const int numInfluencesPerPoint,
TfSpan<const int> faceVertexIndices,
TfSpan<GfVec3f> normals,
const bool inSerial)
{
if (faceVertexIndices.size() != normals.size()) {
TF_WARN("Size of faceVertexIndices [%zu] != size of normals [%zu]",
faceVertexIndices.size(), normals.size());
return false;
}

const _InterleavedInfluencesFn influenceFn{influences};

const int numPoints = influences.size() / numInfluencesPerPoint;
const _FaceVaryingPointIndexFn indexFn{faceVertexIndices, numPoints};

if (skinningMethod == UsdSkelTokens->classicLinear) {
return _SkinNormalsLBS(geomBindTransform, jointXforms, influenceFn, indexFn,
numInfluencesPerPoint, normals, inSerial);
} else if (skinningMethod == UsdSkelTokens->dualQuaternion) {
return _SkinNormalsDQS(geomBindTransform, jointXforms, influenceFn, indexFn,
numInfluencesPerPoint, normals, inSerial);
} else {
TF_WARN("Unknown skinning method: '%s' ", skinningMethod.GetText());
return false;
}
}


} // namespace


Expand Down Expand Up @@ -2269,6 +2304,38 @@ UsdSkelSkinFaceVaryingNormals(const TfToken& skinningMethod,
}


bool
UsdSkelSkinFaceVaryingNormals(const TfToken& skinningMethod,
const GfMatrix3d& geomBindTransform,
TfSpan<const GfMatrix3d> jointXforms,
TfSpan<const GfVec2f> influences,
const int numInfluencesPerPoint,
TfSpan<const int> faceVertexIndices,
TfSpan<GfVec3f> normals,
const bool inSerial)
{
return _SkinFaceVaryingNormals(
skinningMethod, geomBindTransform, jointXforms, influences,
numInfluencesPerPoint, faceVertexIndices, normals, inSerial);
}


bool
UsdSkelSkinFaceVaryingNormals(const TfToken& skinningMethod,
const GfMatrix3f& geomBindTransform,
TfSpan<const GfMatrix3f> jointXforms,
TfSpan<const GfVec2f> influences,
const int numInfluencesPerPoint,
TfSpan<const int> faceVertexIndices,
TfSpan<GfVec3f> normals,
const bool inSerial)
{
return _SkinFaceVaryingNormals(
skinningMethod, geomBindTransform, jointXforms, influences,
numInfluencesPerPoint, faceVertexIndices, normals, inSerial);
}


bool
UsdSkelSkinNormalsLBS(const GfMatrix3d& geomBindTransform,
TfSpan<const GfMatrix3d> jointXforms,
Expand Down
25 changes: 25 additions & 0 deletions pxr/usd/usdSkel/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,31 @@ UsdSkelSkinFaceVaryingNormals(const TfToken& skinningMethod,
bool inSerial=false);


/// \overload
USDSKEL_API
bool
UsdSkelSkinFaceVaryingNormals(const TfToken& skinningMethod,
const GfMatrix3d& geomBindTransform,
TfSpan<const GfMatrix3d> jointXforms,
TfSpan<const GfVec2f> influences,
int numInfluencesPerPoint,
TfSpan<const int> faceVertexIndices,
TfSpan<GfVec3f> normals,
bool inSerial=false);

/// \overload
USDSKEL_API
bool
UsdSkelSkinFaceVaryingNormals(const TfToken& skinningMethod,
const GfMatrix3f& geomBindTransform,
TfSpan<const GfMatrix3f> jointXforms,
TfSpan<const GfVec2f> influences,
int numInfluencesPerPoint,
TfSpan<const int> faceVertexIndices,
TfSpan<GfVec3f> normals,
bool inSerial=false);


USDSKEL_API
bool
UsdSkelSkinNormalsLBS(const GfMatrix3d& geomBindTransform,
Expand Down
29 changes: 29 additions & 0 deletions pxr/usdImaging/usdSkelImaging/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,32 @@ pxr_library(usdSkelImaging
plugInfo.json
shaders/skinning.glslfx
)

# Build tests
pxr_build_test(testUsdSkelImagingSkeletonAdapter
LIBRARIES
usdImaging
usdShade
usdGeom
usdSkel
usd
sdf
hd
tf
gf
arch
CPPFILES
testenv/testUsdSkelImagingSkeletonAdapter.cpp
)

# Install (copy test assets and baselines)
pxr_install_test_dir(
SRC testenv/testUsdSkelImagingSkeletonAdapter
DEST testUsdSkelImagingSkeletonAdapter
)

# Register tests
pxr_register_test(testUsdSkelImagingSkeletonAdapter
COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testUsdSkelImagingSkeletonAdapter"
EXPECTED_RETURN_CODE 0
)
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ _ExtComputationInputComputations(const SdfPath &primPath)
HdPathDataSourceHandle const pathSrc =
HdRetainedTypedSampledDataSource<SdfPath>::New(
primPath.AppendChild(
UsdSkelImagingExtComputationNameTokens->aggregatorComputation));
UsdSkelImagingExtComputationNameTokens->pointsAggregatorComputation));

std::vector<HdDataSourceBaseHandle> values;
values.reserve(names.size());
Expand Down Expand Up @@ -754,13 +754,13 @@ UsdSkelImagingDataSourceResolvedExtComputationPrim(
TRACE_FUNCTION();

if (computationName == UsdSkelImagingExtComputationNameTokens
->computation) {
->pointsComputation) {
return
_ExtComputationPrimDataSource(
std::move(resolvedPrimSource));
}
if (computationName == UsdSkelImagingExtComputationNameTokens
->aggregatorComputation) {
->pointsAggregatorComputation) {
return
_ExtAggregatorComputationPrimDataSource(
std::move(resolvedPrimSource));
Expand Down
Loading
Loading