Skip to content

Commit

Permalink
HYDRA-289 : Fix for USD light intensity too strong (avoid creating Hy…
Browse files Browse the repository at this point in the history
…dra adapters for UFE items created by maya-usd) (#451)

* HYDRA-289 Add checks to prevent creating adapters for UFE items created by maya-usd

* HYDRA-289 Add extra check to prevent creating light adapters for USD's UFE lights in PreFrame light query step

* HYDRA-289 Whitespace changes

* HYDRA-289 Whitespace changes

* HYDRA-289 : Move mayaUsd plugin check for tests into usdUtils

* HYDRA-289 : Move check from usdUtils to mtohUtils

* HYDRA-289 : Revert usdUtils changes

* HYDRA-289 : Add test for ensuring skipping UFE items from maya-usd

* HYDRA-289 Move comments describing UFE to where IsUfeItemFromMayaUsd is declared
  • Loading branch information
debloip-adsk authored and GitHub Enterprise committed Jul 18, 2023
1 parent c1f2bfe commit 947de4b
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 24 deletions.
69 changes: 46 additions & 23 deletions lib/mayaHydra/hydraExtensions/delegates/sceneDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <mayaHydraLib/adapters/renderItemAdapter.h>
#include <mayaHydraLib/delegates/delegateDebugCodes.h>
#include <mayaHydraLib/delegates/delegateRegistry.h>
#include <mayaHydraLib/mayaUtils.h>
#include <mayaHydraLib/utils.h>

#include <pxr/base/gf/matrix4d.h>
Expand Down Expand Up @@ -513,7 +514,7 @@ void MayaHydraSceneDelegate::PreFrame(const MHWRender::MDrawContext& context)
if (!status) {
return;
}
MayaHydraSceneDelegate::Create(dag, lightToAdd.second, _lightAdapters, true);
CreateLightAdapter(dag);
}
_lightsToAdd.clear();
}
Expand Down Expand Up @@ -613,6 +614,10 @@ void MayaHydraSceneDelegate::PreFrame(const MHWRender::MDrawContext& context)
if (!lightPath.isValid()) {
continue;
}
if (IsUfeItemFromMayaUsd(lightPath)) {
// If this is a UFE light created by maya-usd, it will have already added it to Hydra
continue;
}

activelightPaths.push_back(lightPath);

Expand Down Expand Up @@ -645,11 +650,7 @@ void MayaHydraSceneDelegate::PreFrame(const MHWRender::MDrawContext& context)
},
_lightAdapters);
for (const auto& lightPath : activelightPaths) {
Create(
lightPath,
MayaHydraAdapterRegistry::GetLightAdapterCreator(lightPath),
_lightAdapters,
true);
CreateLightAdapter(lightPath);
}
}

Expand Down Expand Up @@ -803,19 +804,28 @@ MayaHydraMaterialAdapterPtr MayaHydraSceneDelegate::GetMaterialAdapter(const Sdf
}

template <typename AdapterPtr, typename Map>
AdapterPtr MayaHydraSceneDelegate::Create(
AdapterPtr MayaHydraSceneDelegate::_CreateAdapter(
const MDagPath& dag,
const std::function<AdapterPtr(MayaHydraDelegateCtx*, const MDagPath&)>& adapterCreator,
Map& adapterMap,
bool isSprim)
{
// Filter for whether we should even attempt to create the adapter

if (!adapterCreator) {
return {};
}

if (IsUfeItemFromMayaUsd(dag)) {
// UFE items that have a Hydra representation will be added to Hydra by maya-usd
return {};
}

// Attempt to create the adapter

TF_DEBUG(MAYAHYDRALIB_DELEGATE_INSERTDAG)
.Msg(
"MayaHydraSceneDelegate::Create::"
"MayaHydraSceneDelegate::_CreateAdapter::"
"found %s: %s\n",
MFnDependencyNode(dag.node()).typeName().asChar(),
dag.fullPathName().asChar());
Expand All @@ -834,6 +844,23 @@ AdapterPtr MayaHydraSceneDelegate::Create(
return adapter;
}

MayaHydraLightAdapterPtr MayaHydraSceneDelegate::CreateLightAdapter(const MDagPath& dagPath)
{
auto lightCreatorFunc = MayaHydraAdapterRegistry::GetLightAdapterCreator(dagPath);
return _CreateAdapter(dagPath, lightCreatorFunc, _lightAdapters, true);
}

MayaHydraCameraAdapterPtr MayaHydraSceneDelegate::CreateCameraAdapter(const MDagPath& dagPath)
{
auto cameraCreatorFunc = MayaHydraAdapterRegistry::GetCameraAdapterCreator(dagPath);
return _CreateAdapter(dagPath, cameraCreatorFunc, _cameraAdapters, true);
}

MayaHydraShapeAdapterPtr MayaHydraSceneDelegate::CreateShapeAdapter(const MDagPath& dagPath) {
auto shapeCreatorFunc = MayaHydraAdapterRegistry::GetShapeAdapterCreator(dagPath);
return _CreateAdapter(dagPath, shapeCreatorFunc, _shapeAdapters);
}

namespace {
bool GetShadingEngineNode(const MRenderItem& ri, MObject& shadingEngineNode)
{
Expand Down Expand Up @@ -909,6 +936,11 @@ void MayaHydraSceneDelegate::OnDagNodeAdded(const MObject& obj)
if (obj.isNull())
return;

if (IsUfeItemFromMayaUsd(obj)) {
// UFE items that have a Hydra representation will be added to Hydra by maya-usd
return;
}

// When not using the mesh adapter we care only about lights for this
// callback. It is used to create a LightAdapter when adding a new light
// in the scene for Hydra rendering.
Expand Down Expand Up @@ -956,25 +988,17 @@ void MayaHydraSceneDelegate::InsertDag(const MDagPath& dag)
return;
}

// Skip UFE nodes coming from USD runtime
// UFE stands for Universal Front End : the goal of the Universal Front End is to create a
// DCC-agnostic component that will allow a DCC to browse and edit data in multiple data models.
// Those will be handled by USD Imaging delegate
MStatus status;
static const MString ufeRuntimeStr = "ufeRuntime";
MPlug ufeRuntimePlug = dagNode.findPlug(ufeRuntimeStr, false, &status);
if ((status == MS::kSuccess) && ufeRuntimePlug.asString() == "USD") {
if (IsUfeItemFromMayaUsd(dag)) {
// UFE items that have a Hydra representation will be added to Hydra by maya-usd
return;
}

// Custom lights don't have MFn::kLight.
if (GetLightsEnabled()) {
if (Create(
dag, MayaHydraAdapterRegistry::GetLightAdapterCreator(dag), _lightAdapters, true))
if (CreateLightAdapter(dag))
return;
}
if (Create(
dag, MayaHydraAdapterRegistry::GetCameraAdapterCreator(dag), _cameraAdapters, true)) {
if (CreateCameraAdapter(dag)) {
return;
}
// We are inserting a single prim and
Expand All @@ -983,8 +1007,7 @@ void MayaHydraSceneDelegate::InsertDag(const MDagPath& dag)
return;
}

auto adapter
= Create(dag, MayaHydraAdapterRegistry::GetShapeAdapterCreator(dag), _shapeAdapters);
auto adapter = CreateShapeAdapter(dag);
if (adapter) {
auto material = adapter->GetMaterial();
if (material != MObject::kNullObj) {
Expand Down Expand Up @@ -1496,7 +1519,7 @@ SdfPath MayaHydraSceneDelegate::GetMaterialId(const SdfPath& id)
if (TfMapLookupPtr(_materialAdapters, materialId) != nullptr) {
return materialId;
}

return _CreateMaterial(materialId, material) ? materialId : _fallbackMaterial;
}

Expand Down
6 changes: 5 additions & 1 deletion lib/mayaHydra/hydraExtensions/delegates/sceneDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,15 @@ class MayaHydraSceneDelegate : public MayaHydraDelegateCtx

private:
template <typename AdapterPtr, typename Map>
AdapterPtr Create(
AdapterPtr _CreateAdapter(
const MDagPath& dag,
const std::function<AdapterPtr(MayaHydraDelegateCtx*, const MDagPath&)>& adapterCreator,
Map& adapterMap,
bool isSprim = false);

MayaHydraLightAdapterPtr CreateLightAdapter(const MDagPath& dagPath);
MayaHydraCameraAdapterPtr CreateCameraAdapter(const MDagPath& dagPath);
MayaHydraShapeAdapterPtr CreateShapeAdapter(const MDagPath& dagPath);

MAYAHYDRALIB_API
bool _GetRenderItem(int fastId, MayaHydraRenderItemAdapterPtr& adapter);
Expand Down
30 changes: 30 additions & 0 deletions lib/mayaHydra/hydraExtensions/mayaUtils.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@

#include "mayaUtils.h"

#include <maya/MFnDagNode.h>
#include <maya/MGlobal.h>
#include <maya/MPlug.h>
#include <maya/MSelectionList.h>

MStatus GetDagPathFromNodeName(const MString& nodeName, MDagPath& outDagPath)
Expand All @@ -20,3 +22,31 @@ MStatus GetMayaMatrixFromDagPath(const MDagPath& dagPath, MMatrix& outMatrix)
outMatrix = dagPath.inclusiveMatrix(&status);
return status;
}

bool IsUfeItemFromMayaUsd(const MDagPath& dagPath, MStatus* returnStatus)
{
static const MString ufeRuntimeAttributeName = "ufeRuntime";
static const MString mayaUsdUfeRuntimeName = "USD";

MFnDagNode dagNode(dagPath);
MStatus ufePlugSearchStatus;
MPlug ufeRuntimePlug = dagNode.findPlug(ufeRuntimeAttributeName, false, &ufePlugSearchStatus);
if (returnStatus) {
*returnStatus = ufePlugSearchStatus;
}
return ufePlugSearchStatus && ufeRuntimePlug.asString() == mayaUsdUfeRuntimeName;
}

bool IsUfeItemFromMayaUsd(const MObject& obj, MStatus* returnStatus)
{
MDagPath dagPath;
MStatus dagPathSearchStatus = MDagPath::getAPathTo(obj, dagPath);
if (!dagPathSearchStatus) {
if (returnStatus) {
*returnStatus = dagPathSearchStatus;
}
return false;
}

return IsUfeItemFromMayaUsd(dagPath, returnStatus);
}
34 changes: 34 additions & 0 deletions lib/mayaHydra/hydraExtensions/mayaUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,37 @@ MStatus GetDagPathFromNodeName(const MString& nodeName, MDagPath& outDagPath);
*/
MAYAHYDRALIB_API
MStatus GetMayaMatrixFromDagPath(const MDagPath& dagPath, MMatrix& outMatrix);

/**
* @brief Determines whether a given DAG path points to a UFE item created by maya-usd
*
* @usage Determines whether a given DAG path points to a UFE item created by maya-usd. UFE stands
* for Universal Front End : the goal of the Universal Front End is to create a DCC-agnostic
* component that will allow a DCC to browse and edit data in multiple data models.
*
* @param[in] dagPath is the DAG path of the node in the Maya scene graph.
* @param[out] returnStatus is an optional output variable to return whether the operation was
* successful. Default value is nullptr (not going to store the result status).
*
* @return True if the item pointed to by dagPath is a UFE item created by maya-usd, false
* otherwise.
*/
MAYAHYDRALIB_API
bool IsUfeItemFromMayaUsd(const MDagPath& dagPath, MStatus* returnStatus = nullptr);

/**
* @brief Determines whether a given object is a UFE item created by maya-usd
*
* @usage Determines whether a given object is a UFE item created by maya-usd. UFE stands
* for Universal Front End : the goal of the Universal Front End is to create a DCC-agnostic
* component that will allow a DCC to browse and edit data in multiple data models.
*
* @param[in] obj is the object representing the DAG node.
* @param[out] returnStatus is an optional output variable to return whether the operation was
* successful. Default value is nullptr (not going to store the result status).
*
* @return True if the item represented by obj is a UFE item created by maya-usd, false
* otherwise.
*/
MAYAHYDRALIB_API
bool IsUfeItemFromMayaUsd(const MObject& obj, MStatus* returnStatus = nullptr);
1 change: 1 addition & 0 deletions test/lib/mayaUsd/render/mayaToHydra/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ set(TEST_SCRIPT_FILES
testStageAddPrim.py
cpp/testCppFramework.py
cpp/testMayaSceneFlattening.py
cpp/testMayaUsdUfeItems.py
)

# Test use of mesh adapter code for mesh support, using environment variable.
Expand Down
1 change: 1 addition & 0 deletions test/lib/mayaUsd/render/mayaToHydra/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ target_sources(${TARGET_NAME}
mayaHydraCppTestsCmd.cpp
testCppFramework.cpp
testMayaSceneFlattening.cpp
testMayaUsdUfeItems.cpp
testUtils.cpp
)

Expand Down
35 changes: 35 additions & 0 deletions test/lib/mayaUsd/render/mayaToHydra/cpp/testMayaUsdUfeItems.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

#include "testUtils.h"

#include <mayaHydraLib/mayaUtils.h>
#include <mayaHydraLib/utils.h>

#include <pxr/imaging/hd/tokens.h>

#include <maya/MViewport2Renderer.h>

#include <gtest/gtest.h>

PXR_NAMESPACE_USING_DIRECTIVE

using namespace MAYAHYDRA_NS;

TEST(MayaUsdUfeItems, skipUsdUfeItems)
{
// Setup inspector for the first scene index
const SceneIndicesVector& sceneIndices = GetTerminalSceneIndices();
ASSERT_GT(sceneIndices.size(), static_cast<size_t>(0));
SceneIndexInspector inspector(sceneIndices.front());

// Check if there are UFE prims that contain data
FindPrimPredicate findCubePrimPredicate
= [](const HdSceneIndexBasePtr& sceneIndex, const SdfPath& primPath) -> bool {
std::string primPathString = primPath.GetAsString();
bool isUfeItem = primPathString.find("ufe", 0) < std::string::npos;
HdSceneIndexPrim prim = sceneIndex->GetPrim(primPath);
bool containsData = HdContainerDataSource::Cast(prim.dataSource) != nullptr;
return isUfeItem && containsData;
};
PrimEntriesVector foundPrims = inspector.FindPrims(findCubePrimPredicate, 1);
EXPECT_EQ(foundPrims.size(), static_cast<size_t>(0));
}
44 changes: 44 additions & 0 deletions test/lib/mayaUsd/render/mayaToHydra/cpp/testMayaUsdUfeItems.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import maya.cmds as cmds

import fixturesUtils
import mtohUtils
import unittest

from testUtils import PluginLoaded

class TestMayaUsdUfeItems(mtohUtils.MayaHydraBaseTestCase):
# MayaHydraBaseTestCase.setUpClass requirement.
_file = __file__

def setupUsdStage(self):
import mayaUsd
import usdUtils
import ufe

self.setHdStormRenderer()

proxyShapeUfePathString, proxyShapeUfePath, proxyShapeUfeItem = usdUtils.createSimpleStage()
stage = mayaUsd.lib.GetPrim(proxyShapeUfePathString).GetStage()

# Create a light prim
rectLightName = "myRectLight"
rectLightPrim = stage.DefinePrim('/' + rectLightName, 'RectLight')
rectLightUfePathString = proxyShapeUfePathString + ',/' + rectLightName
rectLightUfePath = ufe.PathString.path(rectLightUfePathString)
rectLightUfeItem = ufe.Hierarchy.createItem(rectLightUfePath)

# Create a geometry prim
sphereName = "mySphere"
sphere = cmds.polySphere(name=sphereName)
mayaUsd.lib.PrimUpdaterManager.duplicate(cmds.ls(sphere, long=True)[0], proxyShapeUfePathString)

cmds.refresh()

@unittest.skipUnless(mtohUtils.checkForMayaUsdPlugin(), "Requires Maya USD Plugin.")
def test_SkipMayaUsdUfeItems(self):
self.setupUsdStage()
with PluginLoaded('mayaHydraCppTests'):
cmds.mayaHydraCppTest(f="MayaUsdUfeItems.skipUsdUfeItems")

if __name__ == '__main__':
fixturesUtils.runTests(globals())

0 comments on commit 947de4b

Please sign in to comment.