From 7785d9458d93d0a845d70aada8d9c5c142dd8736 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 19 Oct 2023 15:01:44 -0400 Subject: [PATCH 1/2] Added base color texture and imagery MDL lookup shaders --- apps/cesium.omniverse.dev.kit | 2 +- exts/cesium.omniverse/mdl/cesium.mdl | 113 +++++++++- .../include/cesium/omniverse/FabricMaterial.h | 7 +- .../omniverse/FabricMaterialDefinition.h | 10 +- .../cesium/omniverse/FabricResourceManager.h | 8 +- .../include/cesium/omniverse/FabricUtil.h | 6 +- src/core/include/cesium/omniverse/Tokens.h | 11 +- src/core/src/FabricMaterial.cpp | 82 +++++-- src/core/src/FabricMaterialDefinition.cpp | 16 +- src/core/src/FabricPrepareRenderResources.cpp | 4 +- src/core/src/FabricResourceManager.cpp | 7 +- src/core/src/FabricUtil.cpp | 209 +++++++++++++++++- 12 files changed, 438 insertions(+), 37 deletions(-) diff --git a/apps/cesium.omniverse.dev.kit b/apps/cesium.omniverse.dev.kit index c050db6d0..0149abe8d 100644 --- a/apps/cesium.omniverse.dev.kit +++ b/apps/cesium.omniverse.dev.kit @@ -14,7 +14,7 @@ app = true [settings] app.window.title = "Cesium for Omniverse Testing App" -app.useFabricSceneDelegate = true +app.useFabricSceneDelegate = false app.usdrt.scene_delegate.enableProxyCubes = false app.usdrt.scene_delegate.geometryStreaming.enabled = false omnihydra.parallelHydraSprimSync = false diff --git a/exts/cesium.omniverse/mdl/cesium.mdl b/exts/cesium.omniverse/mdl/cesium.mdl index 2c0540e7f..53560fc51 100644 --- a/exts/cesium.omniverse/mdl/cesium.mdl +++ b/exts/cesium.omniverse/mdl/cesium.mdl @@ -11,6 +11,113 @@ module [[ anno::display_name("Cesium MDL functions") ]]; +annotation annotation_not_connectable(); + +export float4 cesium_base_color_texture_float4( + gltf_texture_lookup_value base_color_texture = gltf_texture_lookup_value() + [[ + anno::hidden(), + annotation_not_connectable() + ]] +) +[[ + anno::display_name("Cesium base color texture lookup float4"), + anno::description("Returns the base color texture as a float4. Returns [0, 0, 0, 0] if the base color texture does not exist."), + anno::author("Cesium GS Inc."), + anno::in_group("Cesium") +]] +{ + return base_color_texture.valid ? base_color_texture.value : float4(0.0); +} + +export float4 cesium_imagery_layer_float4( + gltf_texture_lookup_value imagery_layer = gltf_texture_lookup_value() + [[ + anno::hidden(), + annotation_not_connectable() + ]], + int imagery_layer_index = 0 + [[ + anno::unused() + ]] +) +[[ + anno::display_name("Cesium imagery layer lookup float4"), + anno::description("Returns the imagery layer at the given index as a float4. Returns [0, 0, 0, 0] if the imagery layer does not exist."), + anno::author("Cesium GS Inc."), + anno::in_group("Cesium") +]] +{ + return imagery_layer.valid ? imagery_layer.value : float4(0.0); +} + +export material cesium_material( + uniform color base_color_factor = color(1.0) + [[ + anno::display_name("Base Color Factor"), + anno::description("The base color of the material.") + ]], + uniform float metallic_factor = 0.0 + [[ + anno::hard_range(0.0, 1.0), + anno::display_name("Metallic Factor"), + anno::description("The metalness of the material. Select between dielectric (0.0) and metallic (1.0).") + ]], + + uniform float roughness_factor = 1.0 + [[ + anno::hard_range(0.0, 1.0), + anno::display_name("Roughness Factor"), + anno::description("The roughness of the material. Select between very glossy (0.0) and dull (1.0).") + ]], + uniform color emissive_factor = color(0.0) + [[ + anno::display_name("Emissive Factor"), + anno::description("The emissive color of the material.") + ]], + uniform gltf_alpha_mode alpha_mode = opaque + [[ + anno::display_name("Alpha Mode"), + anno::description("Select how to interpret the alpha value.") + ]], + uniform float base_alpha = 1.0 + [[ + anno::hard_range(0.0, 1.0), + anno::display_name("Base Alpha"), + anno::description("Select between transparent (0.0) and opaque (1.0)."), + anno::enable_if("alpha_mode!=opaque") + ]], + uniform float alpha_cutoff = 0.5 + [[ + anno::hard_range(0.0, 1.0), + anno::display_name("Alpha Cutoff"), + anno::description("Threshold to decide between fully transparent and fully opaque when alpha mode is 'mask'."), + anno::enable_if("alpha_mode==mask") + ]] +) [[ + anno::display_name("Cesium PBR material"), + anno::description("Cesium metallic-roughness material based off glTF PBR model"), + anno::author("Cesium GS Inc."), + anno::in_group("Cesium") +]] = let { + material base = gltf_material( + base_color_factor: base_color_factor, + metallic_factor: metallic_factor, + roughness_factor: roughness_factor, + emissive_factor: emissive_factor, + alpha_mode: alpha_mode, + base_alpha: base_alpha, + alpha_cutoff: alpha_cutoff + ); + +} in material( + thin_walled: base.thin_walled, + surface: base.surface, + volume: base.volume, + ior: base.ior, + geometry: base.geometry +); + float4 alpha_blend(float4 src, float4 dst) { return src * float4(src.w, src.w, src.w, 1.0) + dst * (1.0 - src.w); } @@ -33,9 +140,9 @@ float4 compute_base_color( return base_color; } -export gltf_texture_lookup_value cesium_texture_lookup(*) [[ anno::hidden() ]] = gltf_texture_lookup(); +export gltf_texture_lookup_value cesium_internal_texture_lookup(*) [[ anno::hidden() ]] = gltf_texture_lookup(); -export material cesium_material( +export material cesium_internal_material( gltf_texture_lookup_value imagery_layers_texture = gltf_texture_lookup_value(true, float4(0.0)), uniform color debug_color = color(1.0), // gltf_material inputs below @@ -66,7 +173,7 @@ export material cesium_material( geometry: base.geometry ); -export gltf_texture_lookup_value cesium_imagery_layer_resolver( +export gltf_texture_lookup_value cesium_internal_imagery_layer_resolver( uniform int imagery_layers_count = 0, gltf_texture_lookup_value imagery_layer_0 = gltf_texture_lookup(), gltf_texture_lookup_value imagery_layer_1 = gltf_texture_lookup(), diff --git a/src/core/include/cesium/omniverse/FabricMaterial.h b/src/core/include/cesium/omniverse/FabricMaterial.h index 0323d5360..e83e71b99 100644 --- a/src/core/include/cesium/omniverse/FabricMaterial.h +++ b/src/core/include/cesium/omniverse/FabricMaterial.h @@ -48,6 +48,7 @@ class FabricMaterial { private: void initialize(); + void initializeFromExistingMaterial(const omni::fabric::Path& path); void createMaterial(const omni::fabric::Path& materialPath); void createShader(const omni::fabric::Path& shaderPath, const omni::fabric::Path& materialPath); @@ -76,9 +77,9 @@ class FabricMaterial { const bool _debugRandomColors; const long _stageId; - omni::fabric::Path _shaderPath; - omni::fabric::Path _baseColorTexturePath; - std::vector _imageryLayerPaths; + std::vector _shaderPaths; + std::vector _baseColorTexturePaths; + std::vector> _imageryLayerPaths; std::vector _allPaths; }; diff --git a/src/core/include/cesium/omniverse/FabricMaterialDefinition.h b/src/core/include/cesium/omniverse/FabricMaterialDefinition.h index b59219159..e2f17ad9a 100644 --- a/src/core/include/cesium/omniverse/FabricMaterialDefinition.h +++ b/src/core/include/cesium/omniverse/FabricMaterialDefinition.h @@ -3,6 +3,7 @@ #include #include #include +#include namespace cesium::omniverse { @@ -10,11 +11,17 @@ struct MaterialInfo; class FabricMaterialDefinition { public: - FabricMaterialDefinition(const MaterialInfo& materialInfo, uint64_t imageryLayerCount, bool disableTextures); + FabricMaterialDefinition( + const MaterialInfo& materialInfo, + uint64_t imageryLayerCount, + bool disableTextures, + const pxr::SdfPath& tilesetMaterialPath); [[nodiscard]] bool hasVertexColors() const; [[nodiscard]] bool hasBaseColorTexture() const; [[nodiscard]] uint64_t getImageryLayerCount() const; + [[nodiscard]] bool hasTilesetMaterial() const; + [[nodiscard]] const pxr::SdfPath& getTilesetMaterialPath() const; // Make sure to update this function when adding new fields to the class bool operator==(const FabricMaterialDefinition& other) const; @@ -23,6 +30,7 @@ class FabricMaterialDefinition { bool _hasVertexColors; bool _hasBaseColorTexture; uint64_t _imageryLayerCount; + pxr::SdfPath _tilesetMaterialPath; }; } // namespace cesium::omniverse diff --git a/src/core/include/cesium/omniverse/FabricResourceManager.h b/src/core/include/cesium/omniverse/FabricResourceManager.h index fa405963c..6596a8d62 100644 --- a/src/core/include/cesium/omniverse/FabricResourceManager.h +++ b/src/core/include/cesium/omniverse/FabricResourceManager.h @@ -61,8 +61,12 @@ class FabricResourceManager { bool smoothNormals, long stageId); - std::shared_ptr - acquireMaterial(const MaterialInfo& materialInfo, uint64_t imageryLayerCount, long stageId, int64_t tilesetId); + std::shared_ptr acquireMaterial( + const MaterialInfo& materialInfo, + uint64_t imageryLayerCount, + long stageId, + int64_t tilesetId, + const pxr::SdfPath& tilesetMaterialPath); std::shared_ptr acquireTexture(); diff --git a/src/core/include/cesium/omniverse/FabricUtil.h b/src/core/include/cesium/omniverse/FabricUtil.h index 04ccc1b4b..0f8eb9112 100644 --- a/src/core/include/cesium/omniverse/FabricUtil.h +++ b/src/core/include/cesium/omniverse/FabricUtil.h @@ -34,6 +34,10 @@ void setTilesetTransform(int64_t tilesetId, const glm::dmat4& ecefToUsdTransform void setTilesetId(const omni::fabric::Path& path, int64_t tilesetId); omni::fabric::Path toFabricPath(const pxr::SdfPath& path); omni::fabric::Path joinPaths(const omni::fabric::Path& absolutePath, const omni::fabric::Token& relativePath); -bool isEmpty(const omni::fabric::Path& path); +std::vector +copyMaterial(const omni::fabric::Path& srcMaterialPath, const omni::fabric::Path& dstMaterialPath); +bool materialHasCesiumNodes(const omni::fabric::Path& path); +bool isCesiumNode(const omni::fabric::Token& mdlIdentifier); +omni::fabric::Token getMdlIdentifier(const omni::fabric::Path& path); } // namespace cesium::omniverse::FabricUtil diff --git a/src/core/include/cesium/omniverse/Tokens.h b/src/core/include/cesium/omniverse/Tokens.h index d3aa739b2..b849b614e 100644 --- a/src/core/include/cesium/omniverse/Tokens.h +++ b/src/core/include/cesium/omniverse/Tokens.h @@ -15,14 +15,17 @@ __pragma(warning(push)) __pragma(warning(disable : 4003)) #define USD_TOKENS \ (base_color_texture) \ (cesium) \ - (cesium_imagery_layer_resolver) \ - (cesium_material) \ - (cesium_texture_lookup) \ + (cesium_base_color_texture_float4) \ + (cesium_imagery_layer_float4) \ + (cesium_internal_imagery_layer_resolver) \ + (cesium_internal_material) \ + (cesium_internal_texture_lookup) \ (constant) \ (doubleSided) \ (extent) \ (faceVertexCounts) \ (faceVertexIndices) \ + (imagery_layer) \ (imagery_layer_0) \ (imagery_layer_1) \ (imagery_layer_2) \ @@ -79,6 +82,7 @@ __pragma(warning(push)) __pragma(warning(disable : 4003)) ((inputs_scale, "inputs:scale")) \ ((inputs_tex_coord_index, "inputs:tex_coord_index")) \ ((inputs_texture, "inputs:texture")) \ + ((inputs_imagery_layer, "inputs:imagery_layer")) \ ((inputs_imagery_layer_0, "inputs:imagery_layer_0")) \ ((inputs_imagery_layer_1, "inputs:imagery_layer_1")) \ ((inputs_imagery_layer_2, "inputs:imagery_layer_2")) \ @@ -96,6 +100,7 @@ __pragma(warning(push)) __pragma(warning(disable : 4003)) ((inputs_imagery_layer_14, "inputs:imagery_layer_14")) \ ((inputs_imagery_layer_15, "inputs:imagery_layer_15")) \ ((inputs_imagery_layers_count, "inputs:imagery_layers_count")) \ + ((inputs_imagery_layer_index, "inputs:imagery_layer_index")) \ ((inputs_imagery_layers_texture, "inputs:imagery_layers_texture")) \ ((inputs_vertex_color_name, "inputs:vertex_color_name")) \ ((inputs_wrap_s, "inputs:wrap_s")) \ diff --git a/src/core/src/FabricMaterial.cpp b/src/core/src/FabricMaterial.cpp index c513751c1..9f19c1a84 100644 --- a/src/core/src/FabricMaterial.cpp +++ b/src/core/src/FabricMaterial.cpp @@ -56,7 +56,13 @@ FabricMaterial::FabricMaterial( return; } - initialize(); + if (materialDefinition.hasTilesetMaterial()) { + const auto tilesetMaterialPath = FabricUtil::toFabricPath(materialDefinition.getTilesetMaterialPath()); + initializeFromExistingMaterial(tilesetMaterialPath); + } else { + initialize(); + } + reset(); } @@ -95,24 +101,25 @@ void FabricMaterial::initialize() { const auto shaderPath = FabricUtil::joinPaths(materialPath, FabricTokens::Shader); createShader(shaderPath, materialPath); - _shaderPath = shaderPath; + _shaderPaths.push_back(shaderPath); _allPaths.push_back(shaderPath); if (_materialDefinition.hasBaseColorTexture()) { const auto baseColorTexturePath = FabricUtil::joinPaths(materialPath, FabricTokens::base_color_texture); createTexture(baseColorTexturePath, shaderPath, FabricTokens::inputs_base_color_texture); - _baseColorTexturePath = baseColorTexturePath; + _baseColorTexturePaths.push_back(baseColorTexturePath); _allPaths.push_back(baseColorTexturePath); } const auto imageryLayerCount = getImageryLayerCount(_materialDefinition); + _imageryLayerPaths.resize(imageryLayerCount); if (imageryLayerCount == 1) { // If there's a single imagery layer plug into cesium_material directly // instead of using a cesium_imagery_layer_resolver const auto imageryLayerPath = FabricUtil::joinPaths(materialPath, FabricTokens::imagery_layer_n[0]); createTexture(imageryLayerPath, shaderPath, FabricTokens::inputs_imagery_layers_texture); - _imageryLayerPaths.push_back(imageryLayerPath); + _imageryLayerPaths[0].push_back(imageryLayerPath); _allPaths.push_back(imageryLayerPath); } else if (imageryLayerCount > 1) { const auto imageryLayerResolverPath = FabricUtil::joinPaths(materialPath, FabricTokens::imagery_layer_resolver); @@ -120,11 +127,10 @@ void FabricMaterial::initialize() { imageryLayerResolverPath, shaderPath, FabricTokens::inputs_imagery_layers_texture, imageryLayerCount); _allPaths.push_back(imageryLayerResolverPath); - _imageryLayerPaths.reserve(imageryLayerCount); for (uint64_t i = 0; i < imageryLayerCount; i++) { const auto imageryLayerPath = FabricUtil::joinPaths(materialPath, FabricTokens::imagery_layer_n[i]); createTexture(imageryLayerPath, imageryLayerResolverPath, FabricTokens::inputs_imagery_layer_n[i]); - _imageryLayerPaths.push_back(imageryLayerPath); + _imageryLayerPaths[i].push_back(imageryLayerPath); _allPaths.push_back(imageryLayerPath); } } @@ -134,6 +140,50 @@ void FabricMaterial::initialize() { } } +void FabricMaterial::initializeFromExistingMaterial(const omni::fabric::Path& srcMaterialPath) { + auto srw = UsdUtil::getFabricStageReaderWriter(); + + const auto& dstMaterialPath = _materialPath; + + const auto dstPaths = FabricUtil::copyMaterial(srcMaterialPath, dstMaterialPath); + + const auto imageryLayerCount = getImageryLayerCount(_materialDefinition); + _imageryLayerPaths.resize(imageryLayerCount); + + for (const auto& dstPath : dstPaths) { + srw.createAttribute(dstPath, FabricTokens::_cesium_tilesetId, FabricTypes::_cesium_tilesetId); + _allPaths.push_back(dstPath); + + const auto mdlIdentifier = FabricUtil::getMdlIdentifier(dstPath); + + if (mdlIdentifier == FabricTokens::cesium_base_color_texture_float4) { + if (_materialDefinition.hasBaseColorTexture()) { + // Create a base color texture node to fill the empty slot + const auto baseColorTexturePath = FabricUtil::joinPaths(dstPath, FabricTokens::base_color_texture); + createTexture(baseColorTexturePath, dstPath, FabricTokens::inputs_base_color_texture); + _baseColorTexturePaths.push_back(baseColorTexturePath); + _allPaths.push_back(baseColorTexturePath); + } + } else if (mdlIdentifier == FabricTokens::cesium_imagery_layer_float4) { + const auto imageryLayerIndexFabric = + srw.getAttributeRd(dstPath, FabricTokens::inputs_imagery_layer_index); + const auto imageryLayerIndex = + static_cast(imageryLayerIndexFabric == nullptr ? 0 : *imageryLayerIndexFabric); + + if (imageryLayerIndex < imageryLayerCount) { + const auto imageryLayerPath = FabricUtil::joinPaths(dstPath, FabricTokens::imagery_layer); + createTexture(imageryLayerPath, dstPath, FabricTokens::inputs_imagery_layer); + _imageryLayerPaths[imageryLayerIndex].push_back(imageryLayerPath); + _allPaths.push_back(imageryLayerPath); + } + } + } + + for (const auto& path : _allPaths) { + FabricResourceManager::getInstance().retainPath(path); + } +} + void FabricMaterial::createMaterial(const omni::fabric::Path& materialPath) { auto srw = UsdUtil::getFabricStageReaderWriter(); srw.createPrim(materialPath); @@ -189,7 +239,7 @@ void FabricMaterial::createShader(const omni::fabric::Path& shaderPath, const om *infoImplementationSourceFabric = FabricTokens::sourceAsset; infoMdlSourceAssetFabric->assetPath = Context::instance().getCesiumMdlPathToken(); infoMdlSourceAssetFabric->resolvedPath = pxr::TfToken(); - *infoMdlSourceAssetSubIdentifierFabric = FabricTokens::cesium_material; + *infoMdlSourceAssetSubIdentifierFabric = FabricTokens::cesium_internal_material; // Connect the material terminals to the shader. srw.createConnection( @@ -253,7 +303,7 @@ void FabricMaterial::createTexture( *infoImplementationSourceFabric = FabricTokens::sourceAsset; infoMdlSourceAssetFabric->assetPath = Context::instance().getCesiumMdlPathToken(); infoMdlSourceAssetFabric->resolvedPath = pxr::TfToken(); - *infoMdlSourceAssetSubIdentifierFabric = FabricTokens::cesium_texture_lookup; + *infoMdlSourceAssetSubIdentifierFabric = FabricTokens::cesium_internal_texture_lookup; paramColorSpaceFabric[0] = FabricTokens::inputs_texture; paramColorSpaceFabric[1] = FabricTokens::_auto; @@ -299,7 +349,7 @@ void FabricMaterial::createImageryLayerResolver( *infoImplementationSourceFabric = FabricTokens::sourceAsset; infoMdlSourceAssetFabric->assetPath = Context::instance().getCesiumMdlPathToken(); infoMdlSourceAssetFabric->resolvedPath = pxr::TfToken(); - *infoMdlSourceAssetSubIdentifierFabric = FabricTokens::cesium_imagery_layer_resolver; + *infoMdlSourceAssetSubIdentifierFabric = FabricTokens::cesium_internal_imagery_layer_resolver; // Create connection to shader srw.createConnection( @@ -319,7 +369,9 @@ void FabricMaterial::setMaterial(int64_t tilesetId, const MaterialInfo& material auto srw = UsdUtil::getFabricStageReaderWriter(); - setShaderValues(_shaderPath, materialInfo); + for (auto& shaderPath : _shaderPaths) { + setShaderValues(shaderPath, materialInfo); + } for (const auto& path : _allPaths) { FabricUtil::setTilesetId(path, tilesetId); @@ -334,11 +386,9 @@ void FabricMaterial::setBaseColorTexture( return; } - if (FabricUtil::isEmpty(_baseColorTexturePath)) { - return; + for (auto& baseColorTexturePath : _baseColorTexturePaths) { + setTextureValues(baseColorTexturePath, textureAssetPathToken, textureInfo, texcoordIndex); } - - setTextureValues(_baseColorTexturePath, textureAssetPathToken, textureInfo, texcoordIndex); } void FabricMaterial::setImageryLayer( @@ -354,7 +404,9 @@ void FabricMaterial::setImageryLayer( return; } - setTextureValues(_imageryLayerPaths[imageryLayerIndex], textureAssetPathToken, textureInfo, texcoordIndex); + for (auto& imageryLayerPath : _imageryLayerPaths[imageryLayerIndex]) { + setTextureValues(imageryLayerPath, textureAssetPathToken, textureInfo, texcoordIndex); + } } void FabricMaterial::clearMaterial() { diff --git a/src/core/src/FabricMaterialDefinition.cpp b/src/core/src/FabricMaterialDefinition.cpp index 61e8bf05f..b726bd93c 100644 --- a/src/core/src/FabricMaterialDefinition.cpp +++ b/src/core/src/FabricMaterialDefinition.cpp @@ -14,7 +14,8 @@ namespace cesium::omniverse { FabricMaterialDefinition::FabricMaterialDefinition( const MaterialInfo& materialInfo, uint64_t imageryLayerCount, - bool disableTextures) { + bool disableTextures, + const pxr::SdfPath& tilesetMaterialPath) { auto hasBaseColorTexture = materialInfo.baseColorTexture.has_value(); @@ -26,6 +27,7 @@ FabricMaterialDefinition::FabricMaterialDefinition( _hasVertexColors = materialInfo.hasVertexColors; _hasBaseColorTexture = hasBaseColorTexture; _imageryLayerCount = imageryLayerCount; + _tilesetMaterialPath = tilesetMaterialPath; } bool FabricMaterialDefinition::hasVertexColors() const { @@ -40,6 +42,14 @@ uint64_t FabricMaterialDefinition::getImageryLayerCount() const { return _imageryLayerCount; } +bool FabricMaterialDefinition::hasTilesetMaterial() const { + return !_tilesetMaterialPath.IsEmpty(); +} + +const pxr::SdfPath& FabricMaterialDefinition::getTilesetMaterialPath() const { + return _tilesetMaterialPath; +} + // In C++ 20 we can use the default equality comparison (= default) bool FabricMaterialDefinition::operator==(const FabricMaterialDefinition& other) const { if (_hasVertexColors != other._hasVertexColors) { @@ -54,6 +64,10 @@ bool FabricMaterialDefinition::operator==(const FabricMaterialDefinition& other) return false; } + if (_tilesetMaterialPath != other._tilesetMaterialPath) { + return false; + } + return true; } diff --git a/src/core/src/FabricPrepareRenderResources.cpp b/src/core/src/FabricPrepareRenderResources.cpp index bd32b5e78..c8de2f768 100644 --- a/src/core/src/FabricPrepareRenderResources.cpp +++ b/src/core/src/FabricPrepareRenderResources.cpp @@ -127,8 +127,8 @@ std::vector acquireFabricMeshes( if (shouldAcquireMaterial) { const auto materialInfo = GltfUtil::getMaterialInfo(model, primitive); - const auto fabricMaterial = - fabricResourceManager.acquireMaterial(materialInfo, imageryLayerCount, stageId, tileset.getTilesetId()); + const auto fabricMaterial = fabricResourceManager.acquireMaterial( + materialInfo, imageryLayerCount, stageId, tileset.getTilesetId(), tilesetMaterialPath); fabricMesh.material = fabricMaterial; fabricMesh.materialInfo = materialInfo; diff --git a/src/core/src/FabricResourceManager.cpp b/src/core/src/FabricResourceManager.cpp index eb28cfd47..86d700eb4 100644 --- a/src/core/src/FabricResourceManager.cpp +++ b/src/core/src/FabricResourceManager.cpp @@ -56,7 +56,7 @@ bool FabricResourceManager::shouldAcquireMaterial( } if (!tilesetMaterialPath.IsEmpty()) { - return false; + return FabricUtil::materialHasCesiumNodes(FabricUtil::toFabricPath(tilesetMaterialPath)); } return hasImagery || GltfUtil::hasMaterial(primitive); @@ -181,8 +181,9 @@ std::shared_ptr FabricResourceManager::acquireMaterial( const MaterialInfo& materialInfo, uint64_t imageryLayerCount, long stageId, - int64_t tilesetId) { - FabricMaterialDefinition materialDefinition(materialInfo, imageryLayerCount, _disableTextures); + int64_t tilesetId, + const pxr::SdfPath& tilesetMaterialPath) { + FabricMaterialDefinition materialDefinition(materialInfo, imageryLayerCount, _disableTextures, tilesetMaterialPath); if (useSharedMaterial(materialDefinition)) { return acquireSharedMaterial(materialInfo, materialDefinition, stageId, tilesetId); diff --git a/src/core/src/FabricUtil.cpp b/src/core/src/FabricUtil.cpp index 218f08fb5..5d90b7089 100644 --- a/src/core/src/FabricUtil.cpp +++ b/src/core/src/FabricUtil.cpp @@ -680,8 +680,213 @@ omni::fabric::Path joinPaths(const omni::fabric::Path& absolutePath, const omni: return {fmt::format("{}/{}", absolutePath.getText(), relativePath.getText()).c_str()}; } -bool isEmpty(const omni::fabric::Path& path) { - return omni::fabric::PathC(path) == omni::fabric::kUninitializedPath; +namespace { + +struct FabricConnection { + omni::fabric::Connection* connection; + omni::fabric::Token attributeName; +}; + +std::vector getConnections(const omni::fabric::Path& path) { + std::vector connections; + + auto srw = UsdUtil::getFabricStageReaderWriter(); + const auto attributes = srw.getAttributeNamesAndTypes(path); + const auto& names = attributes.first; + const auto& types = attributes.second; + + for (size_t i = 0; i < names.size(); i++) { + const auto& name = names[i]; + const auto& type = types[i]; + if (type.baseType == omni::fabric::BaseDataType::eConnection) { + const auto connection = srw.getConnection(path, name); + if (connection != nullptr) { + connections.emplace_back(FabricConnection{connection, name}); + } + } + } + + return connections; +} + +bool isOutput(const omni::fabric::Token& attributeName) { + return attributeName == FabricTokens::outputs_out; +} + +bool isConnection(const omni::fabric::Type& attributeType) { + return attributeType.baseType == omni::fabric::BaseDataType::eConnection; +} + +bool isEmptyToken( + const omni::fabric::Path& path, + const omni::fabric::Token& attributeName, + const omni::fabric::Type& attributeType) { + auto srw = UsdUtil::getFabricStageReaderWriter(); + if (attributeType.baseType == omni::fabric::BaseDataType::eToken) { + const auto attributeValue = srw.getAttributeRd(path, attributeName); + if (attributeValue == nullptr || (*attributeValue).size() == 0) { + return true; + } + } + + return false; +} + +std::vector getAttributesToCopy(const omni::fabric::Path& path) { + std::vector attributeNames; + + auto srw = UsdUtil::getFabricStageReaderWriter(); + + const auto attributes = srw.getAttributeNamesAndTypes(path); + const auto& names = attributes.first; + const auto& types = attributes.second; + + for (size_t i = 0; i < names.size(); i++) { + const auto& name = names[i]; + const auto& type = types[i]; + + if (!isOutput(name) && !isConnection(type) && !isEmptyToken(path, name, type)) { + attributeNames.emplace_back(omni::fabric::TokenC(name)); + } + } + + return attributeNames; +} + +struct FabricAttribute { + omni::fabric::Token name; + omni::fabric::Type type; +}; + +std::vector getAttributesToCreate(const omni::fabric::Path& path) { + std::vector attributeNames; + + auto srw = UsdUtil::getFabricStageReaderWriter(); + + const auto attributes = srw.getAttributeNamesAndTypes(path); + const auto& names = attributes.first; + const auto& types = attributes.second; + + for (size_t i = 0; i < names.size(); i++) { + const auto& name = names[i]; + const auto& type = types[i]; + + if (isOutput(name) || isEmptyToken(path, name, type)) { + attributeNames.emplace_back(FabricAttribute{name, type}); + } + } + + return attributeNames; +} + +void getConnectedPrimsRecursive(const omni::fabric::Path& path, std::vector& connectedPaths) { + const auto connections = getConnections(path); + for (const auto& connection : connections) { + const auto it = std::find(connectedPaths.begin(), connectedPaths.end(), connection.connection->path); + if (it == connectedPaths.end()) { + connectedPaths.emplace_back(connection.connection->path); + getConnectedPrimsRecursive(connection.connection->path, connectedPaths); + } + } +} + +std::vector getPrimsInMaterialNetwork(const omni::fabric::Path& path) { + auto srw = UsdUtil::getFabricStageReaderWriter(); + std::vector paths; + paths.push_back(path); + getConnectedPrimsRecursive(path, paths); + return paths; +} + +} // namespace + +std::vector +copyMaterial(const omni::fabric::Path& srcMaterialPath, const omni::fabric::Path& dstMaterialPath) { + auto srw = UsdUtil::getFabricStageReaderWriter(); + const auto isrw = carb::getCachedInterface(); + + const auto srcPaths = getPrimsInMaterialNetwork(srcMaterialPath); + + std::vector dstPaths; + dstPaths.reserve(srcPaths.size()); + + for (const auto& srcPath : srcPaths) { + auto dstPath = omni::fabric::Path(); + + if (srcPath == srcMaterialPath) { + dstPath = dstMaterialPath; + } else { + dstPath = FabricUtil::joinPaths( + dstMaterialPath, omni::fabric::Token(UsdUtil::getSafeName(srcPath.getText()).c_str())); + } + + dstPaths.push_back(dstPath); + + srw.createPrim(dstPath); + + // This excludes connections, outputs, and empty tokens + // The material network will be reconnected later once all the prims have been copied + // The reason for excluding outputs and empty tokens is so that Omniverse doesn't print the warning + // [Warning] [omni.fabric.plugin] Warning: input has no valid data + const auto attributesToCopy = getAttributesToCopy(srcPath); + + isrw->copySpecifiedAttributes( + srw.getId(), srcPath, attributesToCopy.data(), dstPath, attributesToCopy.data(), attributesToCopy.size()); + + // Add the outputs and empty tokens back. This doesn't print a warning. + const auto attributesToCreate = getAttributesToCreate(srcPath); + for (const auto& attribute : attributesToCreate) { + srw.createAttribute(dstPath, attribute.name, attribute.type); + } + } + + // Reconnect the prims + for (size_t i = 0; i < srcPaths.size(); i++) { + const auto& srcPath = srcPaths[i]; + const auto& dstPath = dstPaths[i]; + const auto connections = getConnections(srcPath); + for (const auto& connection : connections) { + const auto it = std::find(srcPaths.begin(), srcPaths.end(), connection.connection->path); + assert(it != srcPaths.end()); // Ensure that all connections are part of the material network + const auto index = it - srcPaths.begin(); + const auto dstConnection = + omni::fabric::Connection{omni::fabric::PathC(dstPaths[index]), connection.connection->attrName}; + srw.createConnection(dstPath, connection.attributeName, dstConnection); + } + } + + return dstPaths; +} + +bool materialHasCesiumNodes(const omni::fabric::Path& path) { + auto srw = UsdUtil::getFabricStageReaderWriter(); + const auto paths = getPrimsInMaterialNetwork(path); + + for (const auto& p : paths) { + const auto mdlIdentifier = getMdlIdentifier(p); + if (isCesiumNode(mdlIdentifier)) { + return true; + } + } + + return false; +} + +bool isCesiumNode(const omni::fabric::Token& mdlIdentifier) { + return mdlIdentifier == FabricTokens::cesium_base_color_texture_float4 || + mdlIdentifier == FabricTokens::cesium_imagery_layer_float4; +} + +omni::fabric::Token getMdlIdentifier(const omni::fabric::Path& path) { + auto srw = UsdUtil::getFabricStageReaderWriter(); + if (srw.attributeExists(path, FabricTokens::info_mdl_sourceAsset_subIdentifier)) { + const auto infoMdlSourceAssetSubIdentifierFabric = + srw.getAttributeRd(path, FabricTokens::info_mdl_sourceAsset_subIdentifier); + if (infoMdlSourceAssetSubIdentifierFabric != nullptr) { + return *infoMdlSourceAssetSubIdentifierFabric; + } + } + return omni::fabric::Token{}; } } // namespace cesium::omniverse::FabricUtil From 67024a8887c3adff643a1d70c44c6ee98b51a498 Mon Sep 17 00:00:00 2001 From: Sean Lilley Date: Thu, 19 Oct 2023 19:29:12 -0400 Subject: [PATCH 2/2] Use initializer list --- src/core/src/FabricMaterialDefinition.cpp | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/core/src/FabricMaterialDefinition.cpp b/src/core/src/FabricMaterialDefinition.cpp index b726bd93c..f73d9e2d9 100644 --- a/src/core/src/FabricMaterialDefinition.cpp +++ b/src/core/src/FabricMaterialDefinition.cpp @@ -15,20 +15,11 @@ FabricMaterialDefinition::FabricMaterialDefinition( const MaterialInfo& materialInfo, uint64_t imageryLayerCount, bool disableTextures, - const pxr::SdfPath& tilesetMaterialPath) { - - auto hasBaseColorTexture = materialInfo.baseColorTexture.has_value(); - - if (disableTextures) { - hasBaseColorTexture = false; - imageryLayerCount = 0; - } - - _hasVertexColors = materialInfo.hasVertexColors; - _hasBaseColorTexture = hasBaseColorTexture; - _imageryLayerCount = imageryLayerCount; - _tilesetMaterialPath = tilesetMaterialPath; -} + const pxr::SdfPath& tilesetMaterialPath) + : _hasVertexColors(materialInfo.hasVertexColors) + , _hasBaseColorTexture(disableTextures ? false : materialInfo.baseColorTexture.has_value()) + , _imageryLayerCount(disableTextures ? 0 : imageryLayerCount) + , _tilesetMaterialPath(tilesetMaterialPath) {} bool FabricMaterialDefinition::hasVertexColors() const { return _hasVertexColors;