-
Notifications
You must be signed in to change notification settings - Fork 13
HYDRA-1098 : Viewport filters for Hydra data #189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
debloip-adsk
merged 45 commits into
dev
from
debloip/HYDRA-1098/viewport-filters-hydra-data
Jan 9, 2025
Merged
Changes from 35 commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
e123772
HYDRA-1098 : Add new pruning scene index
debloip-adsk 3f36ca7
HYDRA-1098 : Implement enable/disable filter
debloip-adsk dc636e5
HYDRA-1098 : Add pruning tokens
debloip-adsk 3258809
HYDRA-1098 : Implement notifications handlers
debloip-adsk 8fd711d
HYDRA-1098 : Workaround for PathInterface + basic integration
debloip-adsk 580eda8
HYDRA-1098 : Implement GetPrim and GetChildPrimPaths
debloip-adsk c68aa74
HYDRA-1098 : Update filter map on enable/disable
debloip-adsk 30387f1
HYDRA-108 : Exclude scene roots
debloip-adsk ae0e6ae
HYDRA-1098 : Add ancestor check
debloip-adsk b157dae
HYDRA-1098 : Handle all the different cases (hopefully)
debloip-adsk 0a29f77
HYDRA-1098 : Refactor common code
debloip-adsk e05f9df
HYDRA-1098 : Refactor common code
debloip-adsk 4b543d2
HYDRA-1098 : Provide accessor for active filters
debloip-adsk 34e68cd
HYDRA-1098 : Adjust comment
debloip-adsk aa23f84
HYDRA-1098 : Legibility improvements
debloip-adsk d313b1b
HYDRA-1098 : Minor touchups for consistency
debloip-adsk 88c4bbc
HYDRA-1098 : Add filtering tokens
debloip-adsk cb21f9a
HYDRA-1098 : Remove unimplementable tokens for now
debloip-adsk 239e0fe
HYDRA-1098 : Implement various filter handlers
debloip-adsk d9b3a65
HYDRA-1098 : Plug Maya filters to Fvp pruning scene index
debloip-adsk 36a1013
HYDRA-1098 : Restructure Maya plugging code
debloip-adsk f8a0f70
HYDRA-1098 : Add comment
debloip-adsk 1fd1afb
HYDRA-1098 : Add filter tests with USD data for polygon and nurbs cur…
debloip-adsk 751dece
HYDRA-1098 : Add filter test with USD data for nurbs patches filter
debloip-adsk e6743e0
HYDRA-1098 : Add filter test with USD data for lights filter
debloip-adsk aed47d4
HYDRA-1098 : Add USD camera filter test
debloip-adsk 97c6f51
HYDRA-1098 : Add 3rd party data producer polygon filter test
debloip-adsk e439c69
HYDRA-1098 : Cleanup
debloip-adsk e7ddbb8
HYDRA-1098 : Add comments
debloip-adsk bbb43b6
HYDRA-1098 : Re-order member variables
debloip-adsk 4a3dcbd
HYDRA-1098 : Make constants const
debloip-adsk 27fa447
HYDRA-1098 : Remove commented debug code
debloip-adsk 44d95e7
HYDRA-1098 : Use excluded scene root
debloip-adsk bd60069
HYDRA-1098 : Add comments
debloip-adsk acbaefc
HYDRA-1098 : Update tests
debloip-adsk b06bc6d
HYDRA-1098 : Minor refactor from code review
debloip-adsk e678d7f
HYDRA-1098 : Remove superflous selection clears
debloip-adsk 0d34fd8
HYDRA-1098 : Update camera reference image
debloip-adsk 274ac73
HYDRA-1098 : Add camera picking test
debloip-adsk 7f0b85a
Merge branch 'dev' into debloip/HYDRA-1098/viewport-filters-hydra-data
debloip-adsk a37d7c8
HYDRA-1098 : Update reference image
debloip-adsk 5a24bca
Merge branch 'dev' into debloip/HYDRA-1098/viewport-filters-hydra-data
debloip-adsk 3fac4d4
Merge branch 'dev' into debloip/HYDRA-1098/viewport-filters-hydra-data
debloip-adsk 3729659
HYDRA-1098 : Revert camera tests
debloip-adsk b7b0114
HYDRA-1098 : Make viewport filter tests less sensitive to visual appe…
debloip-adsk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,344 @@ | ||
| // Copyright 2024 Autodesk | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
| // | ||
|
|
||
| #include "fvpPruningSceneIndex.h" | ||
|
|
||
| #include <pxr/base/tf/staticTokens.h> | ||
| #include <pxr/imaging/hd/filteringSceneIndex.h> | ||
| #include <pxr/imaging/hd/sceneIndexPrimView.h> | ||
| #include <pxr/imaging/hd/tokens.h> | ||
|
|
||
| PXR_NAMESPACE_OPEN_SCOPE | ||
|
|
||
| TF_DEFINE_PUBLIC_TOKENS(FvpPruningTokens, FVP_PRUNING_TOKENS); | ||
|
|
||
| PXR_NAMESPACE_CLOSE_SCOPE | ||
|
|
||
| PXR_NAMESPACE_USING_DIRECTIVE | ||
|
|
||
| namespace { | ||
|
|
||
| template<typename Container> | ||
| bool _HasAncestorInclusiveInContainer(const SdfPath& path, const Container& pathsContainer) { | ||
| SdfPath currPath = path; | ||
| while (!currPath.IsEmpty() && !currPath.IsAbsoluteRootPath()) { | ||
| if (pathsContainer.find(currPath) != pathsContainer.end()) { | ||
| return true; | ||
| } else { | ||
| currPath = currPath.GetParentPath(); | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| bool _MeshesFilterHandler(const HdSceneIndexBaseRefPtr& sceneIndex, const SdfPath& primPath, const HdSceneIndexPrim& prim) | ||
| { | ||
| // Currently we just flat out remove any prim with a mesh type. If we were to add extra checks to make sure this is not | ||
| // a mesh prim that serves another purpose, we would add them here. | ||
| return prim.primType == HdPrimTypeTokens->mesh; | ||
| } | ||
|
|
||
| bool _CapsulesFilterHandler(const HdSceneIndexBaseRefPtr& sceneIndex, const SdfPath& primPath, const HdSceneIndexPrim& prim) | ||
ppt-adsk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| return prim.primType == HdPrimTypeTokens->capsule; | ||
| } | ||
|
|
||
| bool _ConesFilterHandler(const HdSceneIndexBaseRefPtr& sceneIndex, const SdfPath& primPath, const HdSceneIndexPrim& prim) | ||
| { | ||
| return prim.primType == HdPrimTypeTokens->cone; | ||
| } | ||
|
|
||
| bool _CubesFilterHandler(const HdSceneIndexBaseRefPtr& sceneIndex, const SdfPath& primPath, const HdSceneIndexPrim& prim) | ||
| { | ||
| return prim.primType == HdPrimTypeTokens->cube; | ||
| } | ||
|
|
||
| bool _CylindersFilterHandler(const HdSceneIndexBaseRefPtr& sceneIndex, const SdfPath& primPath, const HdSceneIndexPrim& prim) | ||
| { | ||
| return prim.primType == HdPrimTypeTokens->cylinder; | ||
| } | ||
|
|
||
| bool _SpheresFilterHandler(const HdSceneIndexBaseRefPtr& sceneIndex, const SdfPath& primPath, const HdSceneIndexPrim& prim) | ||
| { | ||
| return prim.primType == HdPrimTypeTokens->sphere; | ||
| } | ||
|
|
||
| bool _NurbsCurvesFilterHandler(const HdSceneIndexBaseRefPtr& sceneIndex, const SdfPath& primPath, const HdSceneIndexPrim& prim) | ||
| { | ||
| return prim.primType == HdPrimTypeTokens->nurbsCurves; | ||
| } | ||
|
|
||
| bool _NurbsPatchesFilterHandler(const HdSceneIndexBaseRefPtr& sceneIndex, const SdfPath& primPath, const HdSceneIndexPrim& prim) | ||
| { | ||
| return prim.primType == HdPrimTypeTokens->nurbsPatch; | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| namespace FVP_NS_DEF { | ||
|
|
||
| PruningSceneIndexRefPtr PruningSceneIndex::New(const HdSceneIndexBaseRefPtr &inputSceneIndex) | ||
| { | ||
| return TfCreateRefPtr(new PruningSceneIndex(inputSceneIndex)); | ||
| } | ||
|
|
||
| PruningSceneIndex::PruningSceneIndex(HdSceneIndexBaseRefPtr const &inputSceneIndex) : | ||
| HdSingleInputFilteringSceneIndexBase(inputSceneIndex), | ||
| InputSceneIndexUtils(inputSceneIndex) | ||
| { | ||
| } | ||
|
|
||
| void PruningSceneIndex::AddExcludedSceneRoot(const PXR_NS::SdfPath& sceneRoot) | ||
| { | ||
| _excludedSceneRoots.emplace(sceneRoot); | ||
| } | ||
|
|
||
| bool PruningSceneIndex::_IsExcluded(const PXR_NS::SdfPath& primPath) const | ||
| { | ||
| return _HasAncestorInclusiveInContainer(primPath, _excludedSceneRoots); | ||
| } | ||
|
|
||
| bool PruningSceneIndex::_PrunePrim(const SdfPath& primPath, const HdSceneIndexPrim& prim, const TfToken& pruningToken) const | ||
| { | ||
| if (_IsExcluded(primPath)) { | ||
| return false; | ||
| } | ||
| using FilterHandler = std::function<bool(const HdSceneIndexBaseRefPtr&, const SdfPath&, const HdSceneIndexPrim&)>; | ||
| static std::map<TfToken, FilterHandler> filterHandlers = { | ||
| { FvpPruningTokens->meshes, _MeshesFilterHandler }, | ||
| { FvpPruningTokens->capsules, _CapsulesFilterHandler }, | ||
| { FvpPruningTokens->cones, _ConesFilterHandler }, | ||
| { FvpPruningTokens->cubes, _CubesFilterHandler }, | ||
| { FvpPruningTokens->cylinders, _CylindersFilterHandler }, | ||
| { FvpPruningTokens->spheres, _SpheresFilterHandler }, | ||
| { FvpPruningTokens->nurbsCurves, _NurbsCurvesFilterHandler }, | ||
| { FvpPruningTokens->nurbsPatches, _NurbsPatchesFilterHandler } | ||
| }; | ||
| return filterHandlers[pruningToken](GetInputSceneIndex(), primPath, prim); | ||
ppt-adsk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| bool PruningSceneIndex::_IsAncestorPrunedInclusive(const SdfPath& primPath) const | ||
| { | ||
| return _HasAncestorInclusiveInContainer(primPath, _filtersByPrunedPath); | ||
| } | ||
|
|
||
| HdSceneIndexPrim PruningSceneIndex::GetPrim(const SdfPath& primPath) const | ||
| { | ||
| if (_filtersByPrunedPath.find(primPath) != _filtersByPrunedPath.end()) { | ||
| // Path is pruned out; return nothing. Note that we could also use | ||
| // _IsAncestorPrunedInclusive, but child paths of a pruned out prim | ||
| // should not be reachable in the first place due to GetChildPrimPaths | ||
| // pruning them out as well. | ||
| return {}; | ||
| } | ||
| return GetInputSceneIndex()->GetPrim(primPath); | ||
| } | ||
|
|
||
| SdfPathVector PruningSceneIndex::GetChildPrimPaths(const SdfPath& primPath) const | ||
| { | ||
| SdfPathVector baseChildPaths = GetInputSceneIndex()->GetChildPrimPaths(primPath); | ||
| SdfPathVector editedChildPaths; | ||
| for (const auto& baseChildPath : baseChildPaths) { | ||
| // Only keep child paths which are not pruned out. | ||
| if (_filtersByPrunedPath.find(baseChildPath) == _filtersByPrunedPath.end()) { | ||
| editedChildPaths.emplace_back(baseChildPath); | ||
| } | ||
| } | ||
| return editedChildPaths; | ||
| } | ||
|
|
||
| bool PruningSceneIndex::EnableFilter(const TfToken& pruningToken) | ||
| { | ||
| if (_prunedPathsByFilter.find(pruningToken) != _prunedPathsByFilter.end()) { | ||
| // Filter already enabled, no change needed. | ||
| return false; | ||
| } | ||
|
|
||
| // Enable the filter | ||
| _prunedPathsByFilter[pruningToken] = SdfPathSet(); | ||
|
|
||
| HdSceneIndexObserver::RemovedPrimEntries prunedPrims; | ||
|
|
||
| for (const SdfPath& primPath : HdSceneIndexPrimView(GetInputSceneIndex())) { | ||
| if (_PrunePrim(primPath, GetInputSceneIndex()->GetPrim(primPath), pruningToken)) { | ||
| // Only send notification if it was not already pruned out, either directly or indirectly | ||
| if (!_IsAncestorPrunedInclusive(primPath)) { | ||
| prunedPrims.emplace_back(primPath); | ||
| } | ||
|
|
||
| _InsertEntry(primPath, pruningToken); | ||
| } | ||
| } | ||
|
|
||
| if (!prunedPrims.empty()) { | ||
| _SendPrimsRemoved(prunedPrims); | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| bool PruningSceneIndex::DisableFilter(const TfToken& pruningToken) | ||
| { | ||
| if (_prunedPathsByFilter.find(pruningToken) == _prunedPathsByFilter.end()) { | ||
| // Filter already disabled, no change needed. | ||
| return false; | ||
| } | ||
|
|
||
| HdSceneIndexObserver::AddedPrimEntries unprunedPrims; | ||
|
|
||
| SdfPathSet prunedPaths = _prunedPathsByFilter[pruningToken]; | ||
| for (const auto& primPath : prunedPaths) { | ||
| _RemoveEntry(primPath, pruningToken); | ||
|
|
||
| // Only send notification if it was pruned and no longer is | ||
| if (!_IsAncestorPrunedInclusive(primPath)) { | ||
| unprunedPrims.emplace_back(primPath, GetInputSceneIndex()->GetPrim(primPath).primType); | ||
| } | ||
| } | ||
|
|
||
| // Disable the filter | ||
| _prunedPathsByFilter.erase(pruningToken); | ||
|
|
||
| if (!unprunedPrims.empty()) { | ||
| _SendPrimsAdded(unprunedPrims); | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| std::set<TfToken> PruningSceneIndex::GetActiveFilters() | ||
| { | ||
| std::set<TfToken> pruningTokens; | ||
| for (const auto& filterEntry : _prunedPathsByFilter) { | ||
| pruningTokens.emplace(filterEntry.first); | ||
| } | ||
| return pruningTokens; | ||
| } | ||
|
|
||
| void PruningSceneIndex::_InsertEntry(const PXR_NS::SdfPath& primPath, const PXR_NS::TfToken& pruningToken) | ||
| { | ||
| _prunedPathsByFilter[pruningToken].emplace(primPath); | ||
| _filtersByPrunedPath[primPath].emplace(pruningToken); | ||
| } | ||
|
|
||
| void PruningSceneIndex::_RemoveEntry(const PXR_NS::SdfPath& primPath, const PXR_NS::TfToken& pruningToken) | ||
| { | ||
| if (_prunedPathsByFilter.find(pruningToken) != _prunedPathsByFilter.end()) { | ||
| _prunedPathsByFilter[pruningToken].erase(primPath); | ||
| } | ||
|
|
||
| if (_filtersByPrunedPath.find(primPath) != _filtersByPrunedPath.end()) { | ||
| _filtersByPrunedPath[primPath].erase(pruningToken); | ||
| if (_filtersByPrunedPath[primPath].empty()) { | ||
| _filtersByPrunedPath.erase(primPath); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void PruningSceneIndex::_PrimsAdded( | ||
| const PXR_NS::HdSceneIndexBase &sender, | ||
| const PXR_NS::HdSceneIndexObserver::AddedPrimEntries &entries) | ||
| { | ||
| HdSceneIndexObserver::AddedPrimEntries editedEntries; | ||
|
|
||
| for (const auto& addedEntry : entries) { | ||
| for (const auto& pruningToken : GetActiveFilters()) { | ||
| if (_PrunePrim(addedEntry.primPath, GetInputSceneIndex()->GetPrim(addedEntry.primPath), pruningToken)) { | ||
| _InsertEntry(addedEntry.primPath, pruningToken); | ||
| } | ||
| } | ||
|
|
||
| // Only send notification if not pruned | ||
| if (!_IsAncestorPrunedInclusive(addedEntry.primPath)) { | ||
| editedEntries.emplace_back(addedEntry); | ||
| } | ||
| } | ||
|
|
||
| if (!editedEntries.empty()) { | ||
| _SendPrimsAdded(editedEntries); | ||
| } | ||
| } | ||
|
|
||
| void PruningSceneIndex::_PrimsRemoved( | ||
| const PXR_NS::HdSceneIndexBase &sender, | ||
| const PXR_NS::HdSceneIndexObserver::RemovedPrimEntries &entries) | ||
| { | ||
| HdSceneIndexObserver::RemovedPrimEntries editedEntries; | ||
|
|
||
| for (const auto& removedEntry : entries) { | ||
| if (!_IsAncestorPrunedInclusive(removedEntry.primPath)) { | ||
| // Prim was not pruned; forward the notification | ||
| editedEntries.emplace_back(removedEntry); | ||
| } else { | ||
| // Prim was pruned; we have either already sent a PrimsRemoved | ||
| // notification from EnableFilter() or have prevented the original | ||
| // PrimsAdded notification from being forwarded in the first place. | ||
| // No need to send a PrimsRemoved notification for a prim that | ||
| // doesn't exist, just remove the pruning entry. | ||
| for (const auto& pruningToken : GetActiveFilters()) { | ||
| _RemoveEntry(removedEntry.primPath, pruningToken); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (!editedEntries.empty()) { | ||
| _SendPrimsRemoved(editedEntries); | ||
| } | ||
| } | ||
|
|
||
| void PruningSceneIndex::_PrimsDirtied( | ||
| const PXR_NS::HdSceneIndexBase &sender, | ||
| const PXR_NS::HdSceneIndexObserver::DirtiedPrimEntries &entries) | ||
| { | ||
| HdSceneIndexObserver::RemovedPrimEntries removedEntries; | ||
| HdSceneIndexObserver::AddedPrimEntries addedEntries; | ||
| HdSceneIndexObserver::DirtiedPrimEntries editedEntries; | ||
|
|
||
| for (const auto& dirtiedEntry : entries) { | ||
| bool wasInitiallyPruned = _IsAncestorPrunedInclusive(dirtiedEntry.primPath); | ||
|
|
||
| HdSceneIndexPrim dirtiedPrim = GetInputSceneIndex()->GetPrim(dirtiedEntry.primPath); | ||
|
|
||
| for (const auto& pruningToken : GetActiveFilters()) { | ||
| if (_PrunePrim(dirtiedEntry.primPath, dirtiedPrim, pruningToken)) { | ||
| _InsertEntry(dirtiedEntry.primPath, pruningToken); | ||
| } else { | ||
| _RemoveEntry(dirtiedEntry.primPath, pruningToken); | ||
| } | ||
| } | ||
|
|
||
| bool isNowPruned = _IsAncestorPrunedInclusive(dirtiedEntry.primPath); | ||
|
|
||
| if (!wasInitiallyPruned && isNowPruned) { | ||
| removedEntries.emplace_back(dirtiedEntry.primPath); | ||
| } else if (wasInitiallyPruned && !isNowPruned) { | ||
| addedEntries.emplace_back(dirtiedEntry.primPath, dirtiedPrim.primType); | ||
| } else { | ||
| editedEntries.emplace_back(dirtiedEntry); | ||
| } | ||
| } | ||
|
|
||
| if (!removedEntries.empty()) { | ||
| _SendPrimsRemoved(removedEntries); | ||
| } | ||
| if (!addedEntries.empty()) { | ||
| _SendPrimsAdded(addedEntries); | ||
| } | ||
| if (!editedEntries.empty()) { | ||
| _SendPrimsDirtied(editedEntries); | ||
| } | ||
| } | ||
|
|
||
| } // namespace FVP_NS_DEF | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.