Skip to content

Commit

Permalink
HYDRA-599 : Add data producer scene index interface in viewport API
Browse files Browse the repository at this point in the history
  • Loading branch information
lanierd-adsk committed Nov 23, 2023
1 parent 396c290 commit ba3b9b4
Show file tree
Hide file tree
Showing 73 changed files with 3,607 additions and 72 deletions.
1 change: 1 addition & 0 deletions lib/flowViewport/API/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ set(HEADERS
fvpVersionInterface.h
fvpInformationInterface.h
fvpInformationClient.h
fvpDataProducerSceneIndexInterface.h
)

# -----------------------------------------------------------------------------
Expand Down
102 changes: 102 additions & 0 deletions lib/flowViewport/API/fvpDataProducerSceneIndexInterface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//
// Copyright 2023 Autodesk, Inc. All rights reserved.
//
// 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.
//

#ifndef FLOW_VIEWPORT_API_DATA_PRODUCER_SCENE_INDEX_INTERFACE_H
#define FLOW_VIEWPORT_API_DATA_PRODUCER_SCENE_INDEX_INTERFACE_H

//Local headers
#include "flowViewport/api.h"

//Hydra headers
#include <pxr/imaging/hd/sceneIndex.h>

namespace FVP_NS_DEF
{
/**
* Interface to manage data producer scene indices in an Hydra viewport. A data producer scene index is a scene index that adds primitives to the current rendering.
* These new primitives are created without the need of a DCC object or a USD stage.
* To get an instance of the DataProducerSceneIndexInterface class, please use :
* Fvp::DataProducerSceneIndexInterface& dataProducerSceneIndexInterface = Fvp::DataProducerSceneIndexInterface::get();
*/
class DataProducerSceneIndexInterface
{
public:

/// Interface accessor
static FVP_API DataProducerSceneIndexInterface& get();

/// Use this string in the viewport identifier parameters, named "hydraViewportId" in this class, to apply the data producer scene index to all viewports.
static FVP_API const std::string allViewports;

/// Use this string in the AddDataProducerSceneIndex method for the "rendererNames" parameter to apply to all renderers.
static FVP_API const std::string allRenderers;

/**
* @brief Adds a custom data producer scene index.
*
* Adds a custom data producer scene index and associate it to be used in the same rendering as the hydra viewport whose identifier is hydraViewportId
* (or all hydra viewports if hydraViewportId is DataProducerSceneIndexInterface::allViewports).
* Basically, we merge this scene index with the others scene indices from the viewport which are the usd stages, the DCC native
* data and any others custom data producer scene indices like this one.
*
* @param[in] customDataProducerSceneIndex is the custom scene index to add.
*
* @param[in] dccNode is a MObject* for Maya or an INode* for 3ds max, if you provide the pointer value, then we automatically track some events such as transform
* or visibility updated and we hide automatically the primitives from the data producer scene index.
* If it is a nullptr, we won't do anything if the node's attributes changes.
* Basically, this is a way for you to set the DCC node as a parent node for all your primitives from the scene index.
*
* @param[in] hydraViewportId is an hydra viewport string identifier to which _customDataProducerSceneIndex needs to be associated to.
* Set it to DataProducerSceneIndexInterface::allViewports to add this data producer scene index to all viewports.
* To retrieve a specific hydra viewport identifier, please use the InformationInterface class.
*
* @param[in] rendererNames : are the Hydra renderer names to which this scene index should be added.
* This is only used when hydraViewportId is set to DataProducerSceneIndexInterface::allViewports, meaning you want to add this scene index to all viewports
* that are using these renderers.
* To apply to multiple renderers, use a separator such as ",". E.g : "GL, Arnold". We are actually looking for the render delegate's name in this string.
* Set this parameter to DataProducerSceneIndexInterface::allRenderers to add your scene index to all viewports whatever their renderer is.
*
* @param[in] customDataProducerSceneIndexRootPathForInsertion is the root path for insertion used as a second parameter of HdRenderIndex::InsertSceneIndex method.
* e.g : renderIndex.InsertSceneIndex(_customDataProducerSceneIndex, _customDataProducerSceneIndexRootPathForInsertion);
*
*/
virtual void addDataProducerSceneIndex(const PXR_NS::HdSceneIndexBaseRefPtr& customDataProducerSceneIndex,
void* dccNode = nullptr,
const std::string& hydraViewportId = allViewports,
const std::string& rendererNames = allRenderers,
const PXR_NS::SdfPath& customDataProducerSceneIndexRootPathForInsertion = PXR_NS::SdfPath::AbsoluteRootPath()
) = 0;

/**
* @brief Removes a custom data producer scene index.
*
* Removes a custom data producer scene index, this scene index will not participate any more to the rendering of the given viewport(s).
*
* @param[in] customDataProducerSceneIndex is the custom scene index to remove.
*
* @param[in] hydraViewportId is the hydra viewport string identifier to which _customDataProducerSceneIndex was associated to or DataProducerSceneIndexInterface::allViewports
* if it was applied to all viewports.
*/
virtual void removeViewportDataProducerSceneIndex(const PXR_NS::HdSceneIndexBaseRefPtr& customDataProducerSceneIndex,
const std::string& hydraViewportId = allViewports
) = 0;
};

}//end of namespace FVP_NS_DEF

#endif //FLOW_VIEWPORT_API_DATA_PRODUCER_SCENE_INDEX_INTERFACE_H
2 changes: 2 additions & 0 deletions lib/flowViewport/API/interfacesImp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ target_sources(${TARGET_NAME}
fvpSelectionInterfaceImp.cpp
fvpVersionInterfaceImp.cpp
fvpInformationInterfaceImp.cpp
fvpDataProducerSceneIndexInterfaceImp.cpp
)

set(HEADERS
fvpSelectionInterfaceImp.h
fvpVersionInterfaceImp.h
fvpInformationInterfaceImp.h
fvpDataProducerSceneIndexInterfaceImp.h
)

# -----------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
//
// Copyright 2023 Autodesk, Inc. All rights reserved.
//
// 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 "fvpDataProducerSceneIndexInterfaceImp.h"
#include "fvpInformationInterfaceImp.h"
#include "flowViewport/API/perViewportSceneIndicesData/fvpViewportInformationAndSceneIndicesPerViewportDataManager.h"
#include "flowViewport/sceneIndex/fvpRenderIndexProxy.h"

//Hydra headers
#include <pxr/imaging/hd/renderIndex.h>

//STL Headers
#include <mutex>

namespace
{
std::mutex _dataProducerSceneIndicesThatApplyToAllViewports_mutex;

// Are the scene indices that need to be applied to all viewports
std::set<PXR_NS::FVP_NS_DEF::DataProducerSceneIndexDataBaseRefPtr> _dataProducerSceneIndicesThatApplyToAllViewports;

// Abstract factory to create the scene index data, an implementation is provided by the DCC
FVP_NS::DataProducerSceneIndexDataAbstractFactory* _sceneIndexDataFactory{nullptr};
}

PXR_NAMESPACE_USING_DIRECTIVE

namespace FVP_NS_DEF {

const std::string DataProducerSceneIndexInterface::allViewports = "allViewports";
const std::string DataProducerSceneIndexInterface::allRenderers = "allRenderers";

DataProducerSceneIndexInterface& DataProducerSceneIndexInterface::get()
{
return DataProducerSceneIndexInterfaceImp::get();
}

DataProducerSceneIndexInterfaceImp& DataProducerSceneIndexInterfaceImp::get()
{
static DataProducerSceneIndexInterfaceImp theInterface;
return theInterface;
}

void DataProducerSceneIndexInterfaceImp::addDataProducerSceneIndex(const PXR_NS::HdSceneIndexBaseRefPtr& customDataProducerSceneIndex,
void* dccNode /*= nullptr*/,
const std::string& hydraViewportId /*= allViewports*/,
const std::string& rendererNames /*= allRenderers*/,
const PXR_NS::SdfPath& customDataProducerSceneIndexRootPathForInsertion /*= PXR_NS::SdfPath::AbsoluteRootPath()*/)
{
//_viewportSceneIndex can be a reference on a nullptr meaning the user wants _customDataProducerSceneIndex to be applied in all viewports.
PXR_NS::FVP_NS_DEF::DataProducerSceneIndexDataBaseRefPtr dataProducerSceneIndexData =
_CreateDataProducerSceneIndexData(customDataProducerSceneIndex, rendererNames, customDataProducerSceneIndexRootPathForInsertion, dccNode);

if (DataProducerSceneIndexInterface::allViewports == hydraViewportId){
//Apply this dataProducer scene index to all viewports
_AddDataProducerSceneIndexToAllViewports(dataProducerSceneIndexData);
} else{
//Apply this dataProducer scene index to a single viewport
const ViewportInformationAndSceneIndicesPerViewportData* viewportInfoAndData =
ViewportInformationAndSceneIndicesPerViewportDataManager::Get().GetViewportInfoAndDataFromViewportId(hydraViewportId);
if (viewportInfoAndData){
_AddDataProducerSceneIndexToThisViewport(viewportInfoAndData->GetViewportInformation(), dataProducerSceneIndexData);
}
}
}

void DataProducerSceneIndexInterfaceImp::removeAllViewportDataProducerSceneIndices(ViewportInformationAndSceneIndicesPerViewportData& viewportInformationAndSceneIndicesPerViewportData)
{
auto& renderIndexProxy = viewportInformationAndSceneIndicesPerViewportData.GetRenderIndexProxy();
if(nullptr == renderIndexProxy){
return;
}

auto& dataProducerSceneIndicesDataForthisViewport = viewportInformationAndSceneIndicesPerViewportData.GetDataProducerSceneIndicesData();

for (auto& dataProducerSceneIndicesData : dataProducerSceneIndicesDataForthisViewport){
//Remove it from the render index
if (dataProducerSceneIndicesData){
const auto& sceneIndex = dataProducerSceneIndicesData->GetDataProducerLastSceneIndexChain();
if (sceneIndex){
renderIndexProxy->RemoveSceneIndex(sceneIndex);
}else{
TF_CODING_ERROR("dataProducerSceneIndexData->GetDataProducerLastSceneIndexChain() is a nullptr, that should never happen here.");
}
}
}

dataProducerSceneIndicesDataForthisViewport.clear();
}

void DataProducerSceneIndexInterfaceImp::removeViewportDataProducerSceneIndex(const PXR_NS::HdSceneIndexBaseRefPtr& customDataProducerSceneIndex,
const std::string& hydraViewportId /*= allViewports*/)
{
if (DataProducerSceneIndexInterface::allViewports == hydraViewportId){
//It was applied to all viewports

ViewportInformationAndSceneIndicesPerViewportDataSet& allViewportsInfoAndSceneIndices =
ViewportInformationAndSceneIndicesPerViewportDataManager::Get().GetAllViewportInfoAndData();

//We need to remove it from all viewports where it was applied.
for (auto& viewportInfoAndData : allViewportsInfoAndSceneIndices){
ViewportInformationAndSceneIndicesPerViewportData& nonConstViewportInfoAndData = const_cast<ViewportInformationAndSceneIndicesPerViewportData&>(viewportInfoAndData);
nonConstViewportInfoAndData.RemoveViewportDataProducerSceneIndex(customDataProducerSceneIndex);
}

//Also remove it from the _dataProducerSceneIndicesThatApplyToAllViewports array
auto findResult = std::find_if(_dataProducerSceneIndicesThatApplyToAllViewports.begin(), _dataProducerSceneIndicesThatApplyToAllViewports.end(),
[&customDataProducerSceneIndex](const PXR_NS::FVP_NS_DEF::DataProducerSceneIndexDataBaseRefPtr& dataProducerSIData) {
return (dataProducerSIData && dataProducerSIData->GetDataProducerSceneIndex() == customDataProducerSceneIndex);}
);
if (findResult != _dataProducerSceneIndicesThatApplyToAllViewports.end()){
_dataProducerSceneIndicesThatApplyToAllViewports.erase(findResult);// Which also decreases ref count
}
}else{
//It was applied to a single viewport
auto viewportInformationAndSceneIndicesPerViewportData = ViewportInformationAndSceneIndicesPerViewportDataManager::Get().GetViewportInfoAndDataFromViewportId(hydraViewportId);
viewportInformationAndSceneIndicesPerViewportData->RemoveViewportDataProducerSceneIndex(customDataProducerSceneIndex);
}
}

void DataProducerSceneIndexInterfaceImp::_AddDataProducerSceneIndexToAllViewports(const PXR_NS::FVP_NS_DEF::DataProducerSceneIndexDataBaseRefPtr& dataProducerSceneIndexData)
{
//Remove const from _dataProducerSceneIndexData
PXR_NS::FVP_NS_DEF::DataProducerSceneIndexDataBaseRefPtr dataProducerSceneIndexDataNonConst = dataProducerSceneIndexData;

//This is a block for the mutex lifetime
{
std::lock_guard<std::mutex> lockDataProducerSceneIndicesDataPerViewport(_dataProducerSceneIndicesThatApplyToAllViewports_mutex);

//Check if it is already inside our array
auto findResult = _dataProducerSceneIndicesThatApplyToAllViewports.find(dataProducerSceneIndexDataNonConst);
if (findResult != _dataProducerSceneIndicesThatApplyToAllViewports.cend()){
return;
}

//It is not already in dataProducerSceneIndexDataSet
//Add it with the dataProducer scene indices that need to be applied to all viewports
_dataProducerSceneIndicesThatApplyToAllViewports.insert(dataProducerSceneIndexDataNonConst);
}

//Apply it to all existing hydra viewports
InformationInterface::ViewportInformationSet viewportsInformation;
InformationInterfaceImp::Get().GetViewportsInformation(viewportsInformation);
for (const auto& viewportInfo : viewportsInformation){
_AddDataProducerSceneIndexToThisViewport(viewportInfo, dataProducerSceneIndexData);
}
}

PXR_NS::FVP_NS_DEF::DataProducerSceneIndexDataBaseRefPtr DataProducerSceneIndexInterfaceImp::_CreateDataProducerSceneIndexData(const HdSceneIndexBaseRefPtr& customDataProducerSceneIndex,
const std::string& rendererNames,
const SdfPath& customDataProducerSceneIndexRootPathForInsertion,
void* dccNode)
{
TF_AXIOM(_sceneIndexDataFactory);

if (! _sceneIndexDataFactory){
TF_CODING_ERROR("_sceneIndexDataFactory is a nullptr, it should have been provided by a call to GetDataProducerSceneIndexInterfaceImp()->SetSceneIndexDataFactory");
return nullptr;
}

const PXR_NS::FVP_NS_DEF::DataProducerSceneIndexDataBase::CreationParameters params(customDataProducerSceneIndex, rendererNames, customDataProducerSceneIndexRootPathForInsertion, dccNode);
return _sceneIndexDataFactory->createDataProducerSceneIndexDataBase(params);
}

void DataProducerSceneIndexInterfaceImp::_AddDataProducerSceneIndexToThisViewport(const InformationInterface::ViewportInformation& viewportInformation,
const PXR_NS::FVP_NS_DEF::DataProducerSceneIndexDataBaseRefPtr& dataProducerSceneIndexData)
{
TF_AXIOM(dataProducerSceneIndexData);

const std::string& hydraViewportId = viewportInformation._viewportId;
TF_AXIOM(hydraViewportId.length() > 0);

//Check if there is some filtering per Hydra renderer
const std::string& viewportRendererName = viewportInformation._rendererName;
const std::string& dataProducerSceneIndexApplyToRendererNames = dataProducerSceneIndexData->GetRendererNames();
if ( (! viewportRendererName.empty() )&& (dataProducerSceneIndexApplyToRendererNames != DataProducerSceneIndexInterface::allRenderers) ){
//Filtering per renderer is applied
if (std::string::npos == dataProducerSceneIndexApplyToRendererNames.find(viewportRendererName)){
return; //Ignore the current hydra viewport renderer name is not part of the supported renderers for this dataProducer scene index
}
}

ViewportInformationAndSceneIndicesPerViewportData* viewportInformationAndSceneIndicesPerViewportData =
ViewportInformationAndSceneIndicesPerViewportDataManager::Get().GetViewportInfoAndDataFromViewportId(hydraViewportId);
TF_AXIOM(viewportInformationAndSceneIndicesPerViewportData );

auto& dataProducerSceneIndicesDataForthisViewport = viewportInformationAndSceneIndicesPerViewportData->GetDataProducerSceneIndicesData();
auto findResult = dataProducerSceneIndicesDataForthisViewport.find(dataProducerSceneIndexData);
if (findResult != dataProducerSceneIndicesDataForthisViewport.end()){
return; //Already in our array
}

dataProducerSceneIndicesDataForthisViewport.insert(dataProducerSceneIndexData);//dataProducerSceneIndexData can be shared between multiple viewports

//Add it to the merging scene index if the render inex proxy is present, it may happen that it will be set later
auto renderIndexProxy = viewportInformationAndSceneIndicesPerViewportData->GetRenderIndexProxy();
if (renderIndexProxy && dataProducerSceneIndexData && dataProducerSceneIndexData->GetDataProducerLastSceneIndexChain()){
renderIndexProxy->InsertSceneIndex(dataProducerSceneIndexData->GetDataProducerLastSceneIndexChain(), dataProducerSceneIndexData->GetCustomDataProducerSceneIndexRootPathForInsertion());
}
}

void DataProducerSceneIndexInterfaceImp::hydraViewportSceneIndexAdded(const InformationInterface::ViewportInformation& viewportInfo)
{
//Add the dataProducer scene indices that apply to all viewports to this newly created hydra viewport
std::lock_guard<std::mutex> lockDataProducerSceneIndicesDataPerViewport(_dataProducerSceneIndicesThatApplyToAllViewports_mutex);
for (const PXR_NS::FVP_NS_DEF::DataProducerSceneIndexDataBaseRefPtr& dataProducerSceneIndexData : _dataProducerSceneIndicesThatApplyToAllViewports){
_AddDataProducerSceneIndexToThisViewport(viewportInfo, dataProducerSceneIndexData);
}
}

void DataProducerSceneIndexInterfaceImp::setSceneIndexDataFactory(DataProducerSceneIndexDataAbstractFactory& factory)
{
_sceneIndexDataFactory = &factory;
}

} //End of namespace FVP_NS_DEF
Loading

0 comments on commit ba3b9b4

Please sign in to comment.