Skip to content

Commit

Permalink
Support material interactive updates in the procedural (#2095)
Browse files Browse the repository at this point in the history
* Support material interactive updates in the procedural #2094

* Add changelog
  • Loading branch information
sebastienblor authored Sep 16, 2024
1 parent e6e35d2 commit 3dfb31c
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 19 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@
- [usd#1837](https://github.com/Autodesk/arnold-usd/issues/1837) - Fix motion blur of instanced skinned geometry with animated parent matrix
- [usd#2037](https://github.com/Autodesk/arnold-usd/issues/2027) - Improve instances and objects motion blur coherence.
- [usd#2078](https://github.com/Autodesk/arnold-usd/issues/2078) - Ensure the hydra render callback is always invoked
- [usd#2094](https://github.com/Autodesk/arnold-usd/issues/2094) - Support material interactive updates in the procedural
- [usd#2092](https://github.com/Autodesk/arnold-usd/issues/2092) - Fix interactive update issue when prims visibility is tweaked in the procedural
- [usd#2102](https://github.com/Autodesk/arnold-usd/issues/2102) - Remove hydra warning subdiv_iterations: use type BYTE, not INT


### Build
- [usd#1969](https://github.com/Autodesk/arnold-usd/issues/1969) - Remove support for USD versions older than 21.05

Expand Down
66 changes: 48 additions & 18 deletions libs/translator/reader/reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <pxr/usd/usdUtils/stageCache.h>
#include <pxr/usd/usdRender/settings.h>
#include <pxr/usd/usdShade/nodeGraph.h>
#include <pxr/usd/usdShade/materialBindingAPI.h>

#include <cstdio>
#include <cstring>
Expand Down Expand Up @@ -280,46 +281,75 @@ void UsdArnoldReader::TraverseStage(UsdPrim *rootPrim, UsdArnoldReaderContext &c
}
}
};
const UsdPrim root = (rootPrim) ? *rootPrim : _stage->GetPseudoRoot();
if (!_updating) {
UsdPrimRange range = UsdPrimRange::PreAndPostVisit((rootPrim) ?
*rootPrim : _stage->GetPseudoRoot());
UsdPrimRange range = UsdPrimRange::PreAndPostVisit(root);
TraverseNodes(range, context, threadId, threadCount, doPointInstancer, doSkelData, matrix, nullptr);
} else {

UsdPrim updatedPrim;
bool multiplePrims = false;
bool exportRoot = false;
std::unordered_set<SdfPath, TfHash> dirtyMaterials;

for (const auto& p : _listener._dirtyNodes) {
UsdPrim prim = _stage->GetPrimAtPath(p);
if (!prim)
continue;
if (updatedPrim) {
multiplePrims = true;
} else
updatedPrim = prim;

if (prim == root) {
exportRoot = true;
break;
}
updatedPrim = prim;

if (prim.IsA<UsdShadeMaterial>())
dirtyMaterials.insert(p);
}

if (!updatedPrim)
return;

if (!multiplePrims) {
UsdPrimRange range = UsdPrimRange::PreAndPostVisit(updatedPrim);
UsdGeomPrimvarsAPI primvarsAPI(updatedPrim);
std::vector<std::vector<UsdGeomPrimvar> > &primvarsStack = context.GetThreadContext()->GetPrimvarsStack();
primvarsStack.resize(1);
primvarsStack[0] = primvarsAPI.FindPrimvarsWithInheritance();
TraverseNodes(
range, context, threadId, threadCount, doPointInstancer, doSkelData, matrix, &_listener._dirtyNodes);
} else {
// if there are multiple prims to update,
// we want instead to go through the whole stage and update the primitives that need to
UsdPrimRange range = UsdPrimRange::PreAndPostVisit((rootPrim) ?
*rootPrim : _stage->GetPseudoRoot());
TraverseNodes(range, context, threadId, threadCount, doPointInstancer, doSkelData, matrix, &_listener._dirtyNodes);
if (!dirtyMaterials.empty() && !exportRoot) {
// Loop through all the usd stage, and check which geometries are bound to this material.
// Add them to our dirty nodes list, so that the shapes can be re-exported
UsdPrimRange range(root);
for (auto iter = range.begin(); iter != range.end(); ++iter) {
const UsdPrim &prim(*iter);
// only consider primitives having the material binding api
if (!prim.HasAPI<UsdShadeMaterialBindingAPI>())
continue;

UsdShadeMaterial mat = UsdShadeMaterialBindingAPI(prim).ComputeBoundMaterial(UsdShadeTokens->full);
if (mat && mat.GetPrim()) {
// check if this geometry is bound to our updated material
if (dirtyMaterials.find(mat.GetPrim().GetPath()) != dirtyMaterials.end()) {
// This geometry is bound to one of the modified materials, we need to add it to our list
_listener._dirtyNodes.insert(prim.GetPath());
multiplePrims = true;
}
}
}
}

if (multiplePrims) {
// if there are multiple prims to update,
// we want to go through the whole stage and update the primitives that need to
UsdPrimRange range = UsdPrimRange::PreAndPostVisit(root);
TraverseNodes(
range, context, threadId, threadCount, doPointInstancer, doSkelData, matrix, &_listener._dirtyNodes);
}


// Otherwise, we just have a single primitive to export
UsdPrimRange range = UsdPrimRange::PreAndPostVisit(updatedPrim);
UsdGeomPrimvarsAPI primvarsAPI(updatedPrim);
std::vector<std::vector<UsdGeomPrimvar> > &primvarsStack = context.GetThreadContext()->GetPrimvarsStack();
primvarsStack.resize(1);
primvarsStack[0] = primvarsAPI.FindPrimvarsWithInheritance();
TraverseNodes(range, context, threadId, threadCount, doPointInstancer, doSkelData, matrix, &_listener._dirtyNodes);
}
}

Expand Down

0 comments on commit 3dfb31c

Please sign in to comment.