Fix #128504: check instancer purpose and visibility before processing

During stage load we first look for Prototype prims which are used for
instancing. However, if the instancer itself at the root of that
Prototype hierarchy would later be excluded because of either purpose or
visibility checks, the Prototypes would still be processed. These would
correctly be imported but would end up orphaned because nothing would
later add them to the view layer. Code expecting these objects to be
found within the scene would then fail.

In Animal Logic ALab this situation played out where there was a
`/root/instancer` prim with purpose "render" and we proceeded to load
the prims under the `/root/instancer/Prototypes/...` hierarchy. Since we
were attempting to load just the "proxy" purpose, the `/root/instancer`
was later excluded and the orphaning of those prototypes happened.

The change here moves `collect_point_instancer_proto_paths` to a method
of `USDStageReader` so it can now access `include_by_purpose` and
`include_by_visibility`. And these are now used to prevent unnecessary
Prototype loading.

Pull Request: https://projects.blender.org/blender/blender/pulls/128564
This commit is contained in:
Jesse Yurkovich
2024-10-07 18:08:22 +02:00
committed by Jesse Yurkovich
parent 0a70360eb6
commit 1676c06386
2 changed files with 36 additions and 25 deletions

View File

@@ -107,29 +107,6 @@ static void set_instance_collection(
}
}
static void collect_point_instancer_proto_paths(const pxr::UsdPrim &prim, UsdPathSet &r_paths)
{
/* Note that we use custom filter flags to allow traversing undefined prims,
* because prototype prims may be defined as overs which are skipped by the
* default predicate. */
pxr::Usd_PrimFlagsConjunction filter_flags = pxr::UsdPrimIsActive && pxr::UsdPrimIsLoaded &&
!pxr::UsdPrimIsAbstract;
pxr::UsdPrimSiblingRange children = prim.GetFilteredChildren(filter_flags);
for (const auto &child_prim : children) {
if (pxr::UsdGeomPointInstancer instancer = pxr::UsdGeomPointInstancer(child_prim)) {
pxr::SdfPathVector paths;
instancer.GetPrototypesRel().GetTargets(&paths);
for (const pxr::SdfPath &path : paths) {
r_paths.add(path);
}
}
collect_point_instancer_proto_paths(child_prim, r_paths);
}
}
USDStageReader::USDStageReader(pxr::UsdStageRefPtr stage,
const USDImportParams &params,
const ImportSettings &settings)
@@ -755,6 +732,39 @@ void USDStageReader::create_point_instancer_proto_readers(const UsdPathSet &prot
}
}
void USDStageReader::collect_point_instancer_proto_paths(const pxr::UsdPrim &prim,
UsdPathSet &r_paths) const
{
/* Note that we use custom filter flags to allow traversing undefined prims,
* because prototype prims may be defined as overs which are skipped by the
* default predicate. */
pxr::Usd_PrimFlagsConjunction filter_flags = pxr::UsdPrimIsActive && pxr::UsdPrimIsLoaded &&
!pxr::UsdPrimIsAbstract;
pxr::UsdPrimSiblingRange children = prim.GetFilteredChildren(filter_flags);
for (const auto &child_prim : children) {
if (pxr::UsdGeomPointInstancer instancer = pxr::UsdGeomPointInstancer(child_prim)) {
/* We should only collect the prototype paths from this instancer if it would be included
* by our purpose and visiblity checks, matching what is inside #collect_readers. */
if (!include_by_purpose(instancer)) {
continue;
}
if (!include_by_visibility(instancer)) {
continue;
}
pxr::SdfPathVector paths;
instancer.GetPrototypesRel().GetTargets(&paths);
for (const pxr::SdfPath &path : paths) {
r_paths.add(path);
}
}
collect_point_instancer_proto_paths(child_prim, r_paths);
}
}
UsdPathSet USDStageReader::collect_point_instancer_proto_paths() const
{
UsdPathSet result;
@@ -763,12 +773,12 @@ UsdPathSet USDStageReader::collect_point_instancer_proto_paths() const
return result;
}
io::usd::collect_point_instancer_proto_paths(stage_->GetPseudoRoot(), result);
collect_point_instancer_proto_paths(stage_->GetPseudoRoot(), result);
std::vector<pxr::UsdPrim> protos = stage_->GetPrototypes();
for (const pxr::UsdPrim &proto_prim : protos) {
io::usd::collect_point_instancer_proto_paths(proto_prim, result);
collect_point_instancer_proto_paths(proto_prim, result);
}
return result;

View File

@@ -184,6 +184,7 @@ class USDStageReader {
* does not contain any point instancers.
*/
UsdPathSet collect_point_instancer_proto_paths() const;
void collect_point_instancer_proto_paths(const pxr::UsdPrim &prim, UsdPathSet &r_paths) const;
/**
* Populate the instancer_proto_readers_ map for the prototype prims