diff --git a/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndicesChainManager.cpp b/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndicesChainManager.cpp index 27c3dfdb39..a50aa1ceb3 100644 --- a/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndicesChainManager.cpp +++ b/lib/flowViewport/API/perViewportSceneIndicesData/fvpFilteringSceneIndicesChainManager.cpp @@ -63,7 +63,7 @@ HdSceneIndexBaseRefPtr FilteringSceneIndicesChainManager::createFilteringSceneIn return nullptr;//Not an empty filtering scene indices chain } - //Append the filtering scene indices chain tp the merging scene index from renderIndexProxy + //Append the filtering scene indices chain to the merging scene index from renderIndexProxy _AppendFilteringSceneIndicesChain(viewportInformationAndSceneIndicesPerViewportData, inputSceneIndex); if (viewportInformationAndSceneIndicesPerViewportData.GetLastFilteringSceneIndex() == nullptr){ diff --git a/lib/flowViewport/API/samples/fvpDataProducerSceneIndexExample.cpp b/lib/flowViewport/API/samples/fvpDataProducerSceneIndexExample.cpp index 4b5bdefd7e..56a0e22eec 100644 --- a/lib/flowViewport/API/samples/fvpDataProducerSceneIndexExample.cpp +++ b/lib/flowViewport/API/samples/fvpDataProducerSceneIndexExample.cpp @@ -41,6 +41,7 @@ #include #include #include +#include //TBB headers to use multithreading #include @@ -484,6 +485,9 @@ HdRetainedSceneIndex::AddedPrimEntry DataProducerSceneIndexExample::_CreateCubeP .Build() ); + const GfRange3d cubeRange ({-halfSize, -halfSize, -halfSize}, + { halfSize, halfSize, halfSize}); + //Add the cube primitive HdRetainedSceneIndex::AddedPrimEntry addedPrim; addedPrim.primPath = cubePath; @@ -505,6 +509,14 @@ HdRetainedSceneIndex::AddedPrimEntry DataProducerSceneIndexExample::_CreateCubeP .SetResetXformStack(HdRetainedTypedSampledDataSource::New(true)) //Mark the transform of prototype not inherit from parent .Build(), + //Create an extent attribute to support the viewport bounding box display style, + //if no extent attribute is added, it will not be displayed at all in bounding box display style + HdExtentSchemaTokens->extent, + HdExtentSchema::Builder() + .SetMin(HdRetainedTypedSampledDataSource::New(cubeRange.GetMin())) + .SetMax(HdRetainedTypedSampledDataSource::New(cubeRange.GetMax())) + .Build(), + //create a mesh HdMeshSchemaTokens->mesh, meshDs, @@ -524,6 +536,13 @@ HdRetainedSceneIndex::AddedPrimEntry DataProducerSceneIndexExample::_CreateCubeP .SetMatrix(HdRetainedTypedSampledDataSource::New( transform)).Build(), + //create an extent attribute to easily compute the bounding box from it + HdExtentSchemaTokens->extent, + HdExtentSchema::Builder() + .SetMin(HdRetainedTypedSampledDataSource::New(cubeRange.GetMin())) + .SetMax(HdRetainedTypedSampledDataSource::New(cubeRange.GetMax())) + .Build(), + //create a mesh HdMeshSchemaTokens->mesh, meshDs, diff --git a/lib/flowViewport/sceneIndex/CMakeLists.txt b/lib/flowViewport/sceneIndex/CMakeLists.txt index 8f5a030c43..0e51f3c1c4 100644 --- a/lib/flowViewport/sceneIndex/CMakeLists.txt +++ b/lib/flowViewport/sceneIndex/CMakeLists.txt @@ -10,6 +10,7 @@ target_sources(${TARGET_NAME} fvpSceneIndexUtils.cpp fvpSelectionSceneIndex.cpp fvpWireframeSelectionHighlightSceneIndex.cpp + fvpBBoxSceneIndex.cpp ) set(HEADERS @@ -21,6 +22,7 @@ set(HEADERS fvpSceneIndexUtils.h fvpSelectionSceneIndex.h fvpWireframeSelectionHighlightSceneIndex.h + fvpBBoxSceneIndex.h ) # ----------------------------------------------------------------------------- diff --git a/lib/flowViewport/sceneIndex/fvpBBoxSceneIndex.cpp b/lib/flowViewport/sceneIndex/fvpBBoxSceneIndex.cpp new file mode 100644 index 0000000000..630a1f8338 --- /dev/null +++ b/lib/flowViewport/sceneIndex/fvpBBoxSceneIndex.cpp @@ -0,0 +1,434 @@ +// +// 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. +// + +//Local headers +#include "fvpBBoxSceneIndex.h" + +//USD/Hydra headers +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// This class is a filtering scene index that converts the geometries into a bounding box using the extent attribute. +// If the extent attribute is not present, we draw nothing, so an extent attribute must exist on all primitives for this mode to be supported correctly. + +namespace FVP_NS_DEF { + +PXR_NAMESPACE_USING_DIRECTIVE + +namespace +{ + TfTokenVector + _Concat(const TfTokenVector &a, const TfTokenVector &b) + { + TfTokenVector result; + result.reserve(a.size() + b.size()); + result.insert(result.end(), a.begin(), a.end()); + result.insert(result.end(), b.begin(), b.end()); + return result; + } + + /// A convenience data source implementing the primvar schema from + /// a triple of primvar value, interpolation and role. The latter two + /// are given as tokens. The value can be given either as data source + /// or as thunk returning a data source which is evaluated on each + /// Get. + class _PrimvarDataSource final : public HdContainerDataSource + { + public: + HD_DECLARE_DATASOURCE(_PrimvarDataSource); + + TfTokenVector GetNames() override { + return {HdPrimvarSchemaTokens->primvarValue, + HdPrimvarSchemaTokens->interpolation, + HdPrimvarSchemaTokens->role}; + } + + HdDataSourceBaseHandle Get(const TfToken &name) override { + if (name == HdPrimvarSchemaTokens->primvarValue) { + return _primvarValueSrc; + } + if (name == HdPrimvarSchemaTokens->interpolation) { + return + HdPrimvarSchema::BuildInterpolationDataSource( + _interpolation); + } + if (name == HdPrimvarSchemaTokens->role) { + return + HdPrimvarSchema::BuildRoleDataSource( + _role); + } + + return nullptr; + } + + private: + _PrimvarDataSource( + const HdDataSourceBaseHandle &primvarValueSrc, + const TfToken &interpolation, + const TfToken &role) + : _primvarValueSrc(primvarValueSrc) + , _interpolation(interpolation) + , _role(role) + { + } + + HdDataSourceBaseHandle _primvarValueSrc; + TfToken _interpolation; + TfToken _role; + }; + + /// Base class for container data sources providing primvars. + /// + /// Provides primvars common to bounding boxes display: + /// - displayColor (computed by querying displayColor from the prim data source). + /// + class _PrimvarsDataSource : public HdContainerDataSource + { + public: + + TfTokenVector GetNames() override { + return {HdTokens->displayColor}; + } + + HdDataSourceBaseHandle Get(const TfToken &name) override { + if (name == HdTokens->displayColor) { + //Get the color from the displayColor attribute of the prim + //Works only for maya native data at this time... + GfVec4f color(0,1,0,1); + HdSampledDataSourceHandle valueDs = HdSampledDataSource::Cast(_primSource->Get(name)); + if (valueDs) { + const VtValue value = valueDs->GetValue(0); + if (value.IsHolding()){ + color = value.UncheckedGet(); + }else + if (value.IsHolding()){ + auto color3 = value.UncheckedGet(); + color = GfVec4f(color3[0], color3[1], color3[2], 1.0f); + } + + HdDataSourceBaseHandle const src = + _PrimvarDataSource::New( + HdRetainedTypedSampledDataSource::New( + VtVec3fArray{{color[0], color[1], color[2]}}), + HdPrimvarSchemaTokens->constant, + HdPrimvarSchemaTokens->color); + return src; + } + } + return nullptr; + } + + protected: + _PrimvarsDataSource( + const HdContainerDataSourceHandle &primSource) + : _primSource(primSource) + { + } + + HdContainerDataSourceHandle _primSource; + }; + + /// Base class for prim data sources. + /// + /// Provides: + /// - xform (from the given prim data source) + /// - purpose (from the given prim data source) + /// - visibility (from the given prim data source) + /// - displayStyle (constant) + /// - instancedBy + /// + class _PrimDataSource : public HdContainerDataSource + { + public: + + TfTokenVector GetNames() override { + return { + HdXformSchemaTokens->xform, + HdPurposeSchemaTokens->purpose, + HdVisibilitySchemaTokens->visibility, + HdInstancedBySchemaTokens->instancedBy, + HdLegacyDisplayStyleSchemaTokens->displayStyle }; + } + + HdDataSourceBaseHandle Get(const TfToken &name) override { + if (name == HdXformSchemaTokens->xform || + name == HdPurposeSchemaTokens->purpose || + name == HdVisibilitySchemaTokens->visibility || + name == HdInstancedBySchemaTokens->instancedBy) { + if (_primSource) { + return _primSource->Get(name); + } + return nullptr; + } + if (name == HdLegacyDisplayStyleSchemaTokens->displayStyle) { + static const HdDataSourceBaseHandle src = + HdLegacyDisplayStyleSchema::Builder() + .SetCullStyle( + HdRetainedTypedSampledDataSource::New( + HdCullStyleTokens->back)) + .Build(); + return src; + } + return nullptr; + } + + protected: + _PrimDataSource(const HdContainerDataSourceHandle &primSource) + : _primSource(primSource) + { + } + + HdContainerDataSourceHandle _primSource; + }; + + /// Data source for primvars:points:primvarValue + /// + /// Computes 8 vertices of a box determined by extent of a given prim + /// data source. + /// + class _BoundsPointsPrimvarValueDataSource final : public HdVec3fArrayDataSource + { + public: + HD_DECLARE_DATASOURCE(_BoundsPointsPrimvarValueDataSource); + + VtValue GetValue(Time shutterOffset) { + return VtValue(GetTypedValue(shutterOffset)); + } + + VtVec3fArray GetTypedValue(Time shutterOffset) { + // Get extent from given prim source. + HdExtentSchema extentSchema = + HdExtentSchema::GetFromParent(_primSource); + + GfVec3f exts[2] = { GfVec3f(0.0f), GfVec3f(0.0f) }; + bool extentMinFound = false; + if (HdVec3dDataSourceHandle src = extentSchema.GetMin()) { + exts[0] = GfVec3f(src->GetTypedValue(shutterOffset)); + extentMinFound = true; + } + bool extentMaxFound = false; + if (HdVec3dDataSourceHandle src = extentSchema.GetMax()) { + exts[1] = GfVec3f(src->GetTypedValue(shutterOffset)); + extentMaxFound = true; + } + + if (!extentMinFound || !extentMaxFound) { + // If extent is not given, no bounding box will be displayed + return VtVec3fArray(); + } + + /// Compute 8 points on box. + VtVec3fArray pts(8); + size_t i = 0; + for (size_t j0 = 0; j0 < 2; j0++) { + for (size_t j1 = 0; j1 < 2; j1++) { + for (size_t j2 = 0; j2 < 2; j2++) { + pts[i] = { exts[j0][0], exts[j1][1], exts[j2][2] }; + ++i; + } + } + } + + return pts; + } + + bool GetContributingSampleTimesForInterval( + Time startTime, + Time endTime, + std::vector