diff --git a/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc b/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc index 1a813c4f..0f50b62a 100644 --- a/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc +++ b/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc @@ -757,21 +757,29 @@ class ModelWriter { AddUVTextureShader(material_path, pxr::TfToken("uvmap")); const mjStringVec &textures = *(material->textures); - // Set the values of metallic and roughness. These can come from an ORM - // texture or as a value defined in mjsMaterial_. Occlusion is only present - // in the ORM texture. + // Set the values of metallic, roughness and occlusion. These can come from + // an ORM packed texture, as individual textures, or as a values defined in + // mjsMaterial_ (with the exception of occlusion). pxr::SdfPath metallic_attr = CreateAttributeSpec( data_, preview_surface_shader_path, kTokens->inputsMetallic, pxr::SdfValueTypeNames->Float); pxr::SdfPath roughness_attr = CreateAttributeSpec( data_, preview_surface_shader_path, kTokens->inputsRoughness, pxr::SdfValueTypeNames->Float); - // Find the ORM (occlusion, roughness, metallic) packed-channel texture if - // specified. + // Find the occlusion, roughness, and metallic textures. if (mjTEXROLE_ORM < textures.size()) { std::string orm_texture_name = textures[mjTEXROLE_ORM]; mjsTexture *orm_texture = mjs_asTexture( mjs_findElement(spec_, mjOBJ_TEXTURE, orm_texture_name.c_str())); + std::string occlusion_texture_name = textures[mjTEXROLE_OCCLUSION]; + mjsTexture *occlusion_texture = mjs_asTexture(mjs_findElement( + spec_, mjOBJ_TEXTURE, occlusion_texture_name.c_str())); + std::string roughness_texture_name = textures[mjTEXROLE_ROUGHNESS]; + mjsTexture *roughness_texture = mjs_asTexture(mjs_findElement( + spec_, mjOBJ_TEXTURE, roughness_texture_name.c_str())); + std::string metallic_texture_name = textures[mjTEXROLE_METALLIC]; + mjsTexture *metallic_texture = mjs_asTexture( + mjs_findElement(spec_, mjOBJ_TEXTURE, metallic_texture_name.c_str())); if (orm_texture) { // Create the ORM shader and connect its output to the preview // surface ORM attrs. @@ -788,8 +796,43 @@ class ModelWriter { AddAttributeConnection(data_, metallic_attr, orm_output_attrs[2]); } } else { - SetAttributeDefault(data_, metallic_attr, material->metallic); - SetAttributeDefault(data_, roughness_attr, material->roughness); + if (metallic_texture) { + const std::vector metallic_output_attrs = + AddTextureShader(material_path, metallic_texture->file->c_str(), + pxr::TfToken("metallic"), uvmap_st_output_attr, + {kTokens->outputsRgb}); + if (metallic_output_attrs.size() == 1) { + AddAttributeConnection(data_, metallic_attr, + metallic_output_attrs[0]); + } + } else { + SetAttributeDefault(data_, metallic_attr, material->metallic); + } + if (roughness_texture) { + const std::vector roughness_output_attrs = + AddTextureShader(material_path, roughness_texture->file->c_str(), + pxr::TfToken("roughness"), uvmap_st_output_attr, + {kTokens->outputsRgb}); + if (roughness_output_attrs.size() == 1) { + AddAttributeConnection(data_, roughness_attr, + roughness_output_attrs[0]); + } + } else { + SetAttributeDefault(data_, roughness_attr, material->roughness); + } + if (occlusion_texture) { + pxr::SdfPath occlusion_attr = CreateAttributeSpec( + data_, preview_surface_shader_path, kTokens->inputsOcclusion, + pxr::SdfValueTypeNames->Float); + const std::vector occlusion_output_attrs = + AddTextureShader(material_path, occlusion_texture->file->c_str(), + pxr::TfToken("occlusion"), uvmap_st_output_attr, + {kTokens->outputsRgb}); + if (occlusion_output_attrs.size() == 1) { + AddAttributeConnection(data_, occlusion_attr, + occlusion_output_attrs[0]); + } + } } } // Find the normal texture if specified. diff --git a/test/experimental/usd/plugins/mjcf/mjcf_file_format_test.cc b/test/experimental/usd/plugins/mjcf/mjcf_file_format_test.cc index 9628199e..a1cdbbda 100644 --- a/test/experimental/usd/plugins/mjcf/mjcf_file_format_test.cc +++ b/test/experimental/usd/plugins/mjcf/mjcf_file_format_test.cc @@ -166,56 +166,101 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMaterials) { stage, "/mesh_test/Materials/material_texture/diffuse.inputs:file", pxr::SdfAssetPath("textures/cube.png")); + EXPECT_PRIM_VALID(stage, "/mesh_test/Materials/material_metallic"); + EXPECT_PRIM_VALID(stage, + "/mesh_test/Materials/material_metallic/PreviewSurface"); + ExpectAttributeEqual( + stage, + "/mesh_test/Materials/material_metallic/PreviewSurface.inputs:metallic", + 0.6f); +} + +TEST_F(MjcfSdfFileFormatPluginTest, TestMaterialLayers) { + const std::string xml_path = GetTestDataFilePath(kMaterialsPath); + auto stage = pxr::UsdStage::Open(xml_path); + EXPECT_THAT(stage, testing::NotNull()); + EXPECT_PRIM_VALID(stage, "/mesh_test/Materials/material_layered"); EXPECT_PRIM_VALID(stage, "/mesh_test/Materials/material_layered/uvmap"); EXPECT_PRIM_VALID(stage, "/mesh_test/Materials/material_layered/diffuse"); EXPECT_PRIM_VALID(stage, "/mesh_test/Materials/material_layered/normal"); ExpectAttributeHasConnection( - stage, - "/mesh_test/Materials/material_layered/" - "PreviewSurface.inputs:normal", - "/mesh_test/Materials/material_layered/normal.outputs:rgb"); + stage, + "/mesh_test/Materials/material_layered/" + "PreviewSurface.inputs:normal", + "/mesh_test/Materials/material_layered/normal.outputs:rgb"); ExpectAttributeEqual( - stage, "/mesh_test/Materials/material_layered/normal.inputs:file", - pxr::SdfAssetPath("textures/normal.png")); + stage, "/mesh_test/Materials/material_layered/normal.inputs:file", + pxr::SdfAssetPath("textures/normal.png")); EXPECT_PRIM_VALID(stage, "/mesh_test/Materials/material_layered/orm_packed"); ExpectAttributeHasConnection( - stage, - "/mesh_test/Materials/material_layered/" - "PreviewSurface.inputs:occlusion", - "/mesh_test/Materials/material_layered/orm_packed.outputs:r"); + stage, + "/mesh_test/Materials/material_layered/" + "PreviewSurface.inputs:occlusion", + "/mesh_test/Materials/material_layered/orm_packed.outputs:r"); ExpectAttributeHasConnection( - stage, - "/mesh_test/Materials/material_layered/" - "PreviewSurface.inputs:roughness", - "/mesh_test/Materials/material_layered/orm_packed.outputs:g"); + stage, + "/mesh_test/Materials/material_layered/" + "PreviewSurface.inputs:roughness", + "/mesh_test/Materials/material_layered/orm_packed.outputs:g"); ExpectAttributeHasConnection( - stage, - "/mesh_test/Materials/material_layered/" - "PreviewSurface.inputs:metallic", - "/mesh_test/Materials/material_layered/orm_packed.outputs:b"); + stage, + "/mesh_test/Materials/material_layered/" + "PreviewSurface.inputs:metallic", + "/mesh_test/Materials/material_layered/orm_packed.outputs:b"); ExpectAttributeEqual( - stage, "/mesh_test/Materials/material_layered/orm_packed.inputs:file", - pxr::SdfAssetPath("textures/orm.png")); + stage, "/mesh_test/Materials/material_layered/orm_packed.inputs:file", + pxr::SdfAssetPath("textures/orm.png")); EXPECT_PRIM_VALID(stage, "/mesh_test/Materials/material_layered/emissive"); ExpectAttributeHasConnection( - stage, - "/mesh_test/Materials/material_layered/" - "PreviewSurface.inputs:emissiveColor", - "/mesh_test/Materials/material_layered/emissive.outputs:rgb"); + stage, + "/mesh_test/Materials/material_layered/" + "PreviewSurface.inputs:emissiveColor", + "/mesh_test/Materials/material_layered/emissive.outputs:rgb"); ExpectAttributeEqual( - stage, "/mesh_test/Materials/material_layered/emissive.inputs:file", - pxr::SdfAssetPath("textures/emissive.png")); + stage, "/mesh_test/Materials/material_layered/emissive.inputs:file", + pxr::SdfAssetPath("textures/emissive.png")); +} - EXPECT_PRIM_VALID(stage, "/mesh_test/Materials/material_metallic"); +TEST_F(MjcfSdfFileFormatPluginTest, TestMaterialPBRSeparate) { + const std::string xml_path = GetTestDataFilePath(kMaterialsPath); + auto stage = pxr::UsdStage::Open(xml_path); + + EXPECT_PRIM_VALID(stage, "/mesh_test/Materials/material_pbr_separate"); + EXPECT_PRIM_VALID(stage, "/mesh_test/Materials/material_pbr_separate/uvmap"); EXPECT_PRIM_VALID(stage, - "/mesh_test/Materials/material_metallic/PreviewSurface"); - ExpectAttributeEqual(stage, - "/mesh_test/Materials/material_metallic/PreviewSurface.inputs:metallic", - 0.6f); + "/mesh_test/Materials/material_pbr_separate/occlusion"); + ExpectAttributeHasConnection( + stage, + "/mesh_test/Materials/material_pbr_separate/" + "PreviewSurface.inputs:occlusion", + "/mesh_test/Materials/material_pbr_separate/occlusion.outputs:rgb"); + ExpectAttributeEqual( + stage, "/mesh_test/Materials/material_pbr_separate/occlusion.inputs:file", + pxr::SdfAssetPath("textures/occlusion.png")); + EXPECT_PRIM_VALID(stage, + "/mesh_test/Materials/material_pbr_separate/roughness"); + ExpectAttributeHasConnection( + stage, + "/mesh_test/Materials/material_pbr_separate/" + "PreviewSurface.inputs:roughness", + "/mesh_test/Materials/material_pbr_separate/roughness.outputs:rgb"); + ExpectAttributeEqual( + stage, "/mesh_test/Materials/material_pbr_separate/roughness.inputs:file", + pxr::SdfAssetPath("textures/roughness.png")); + EXPECT_PRIM_VALID(stage, + "/mesh_test/Materials/material_pbr_separate/metallic"); + ExpectAttributeHasConnection( + stage, + "/mesh_test/Materials/material_pbr_separate/" + "PreviewSurface.inputs:metallic", + "/mesh_test/Materials/material_pbr_separate/metallic.outputs:rgb"); + ExpectAttributeEqual( + stage, "/mesh_test/Materials/material_pbr_separate/metallic.inputs:file", + pxr::SdfAssetPath("textures/metallic.png")); } TEST_F(MjcfSdfFileFormatPluginTest, TestGeomRgba) { diff --git a/test/experimental/usd/plugins/mjcf/testdata/materials.xml b/test/experimental/usd/plugins/mjcf/testdata/materials.xml index dfb869d4..3ca1ec8a 100644 --- a/test/experimental/usd/plugins/mjcf/testdata/materials.xml +++ b/test/experimental/usd/plugins/mjcf/testdata/materials.xml @@ -4,6 +4,9 @@ + + + @@ -13,6 +16,11 @@ + + + + + 2d texture="diffuse" normal="normal" /> diff --git a/test/experimental/usd/plugins/mjcf/testdata/textures/metallic.png b/test/experimental/usd/plugins/mjcf/testdata/textures/metallic.png new file mode 100644 index 00000000..a14f5f63 Binary files /dev/null and b/test/experimental/usd/plugins/mjcf/testdata/textures/metallic.png differ diff --git a/test/experimental/usd/plugins/mjcf/testdata/textures/occlusion.png b/test/experimental/usd/plugins/mjcf/testdata/textures/occlusion.png new file mode 100644 index 00000000..a14f5f63 Binary files /dev/null and b/test/experimental/usd/plugins/mjcf/testdata/textures/occlusion.png differ diff --git a/test/experimental/usd/plugins/mjcf/testdata/textures/roughness.png b/test/experimental/usd/plugins/mjcf/testdata/textures/roughness.png new file mode 100644 index 00000000..a14f5f63 Binary files /dev/null and b/test/experimental/usd/plugins/mjcf/testdata/textures/roughness.png differ