Commit: b67b84bd5d6dea88a8941abe4205556a4a74f549 Author: Michael Kowalski Date: Fri Jan 27 10:29:58 2023 -0500 Branches: master https://developer.blender.org/rBb67b84bd5d6dea88a8941abe4205556a4a74f549
Fix T103984: USD exports pass usdchecker These changes were authored by Michael B Johnson (drwave). The default Blender USD export currently produces files that trigger errors in the usdchecker that ships with USD 22.11. The changes are: - Set the defaultPrim if no defaultPrim is set. This sets it to the first prim in the hierarchy which matches the behaviour of Pixar's referencing (where referencing a USD layer without a defaultPrim will pick the first prim) as well as matches the logic in Pixar's Maya USD exporter code. - Applies the MaterialBindingAPI to prims with material binding attributes. This is a relatively new requirement for USD as it will help for efficiency with upcoming changes to Hydra. - Removes the preview scope in the USD shader hierarchy, because it is no longer valid for shaders to have any non-container ancestors in their hierarchy up until the enclosing Material prim. Reviewed by: Michael Kowalski Differential Revision: https://developer.blender.org/D17041 =================================================================== M source/blender/io/usd/intern/usd_capi_export.cc M source/blender/io/usd/intern/usd_writer_material.cc M source/blender/io/usd/intern/usd_writer_mesh.cc M source/blender/io/usd/tests/usd_export_test.cc =================================================================== diff --git a/source/blender/io/usd/intern/usd_capi_export.cc b/source/blender/io/usd/intern/usd_capi_export.cc index 1d33ca3a13c..7ab244f18f0 100644 --- a/source/blender/io/usd/intern/usd_capi_export.cc +++ b/source/blender/io/usd/intern/usd_capi_export.cc @@ -7,6 +7,8 @@ #include <pxr/base/plug/registry.h> #include <pxr/pxr.h> +#include <pxr/usd/usd/prim.h> +#include <pxr/usd/usd/primRange.h> #include <pxr/usd/usd/stage.h> #include <pxr/usd/usdGeom/tokens.h> @@ -138,6 +140,17 @@ static void export_startjob(void *customdata, } iter.release_writers(); + + /* Set the default prim if it doesn't exist */ + if (!usd_stage->GetDefaultPrim()) { + /* Use TraverseAll since it's guaranteed to be depth first and will get the first top level + * prim, and is less verbose than getting the PseudoRoot + iterating its children.*/ + for (auto prim : usd_stage->TraverseAll()) { + usd_stage->SetDefaultPrim(prim); + break; + } + } + usd_stage->GetRootLayer()->Save(); /* Finish up by going back to the keyframe that was current before we started. */ diff --git a/source/blender/io/usd/intern/usd_writer_material.cc b/source/blender/io/usd/intern/usd_writer_material.cc index 7e744b74f61..3e2f34b1b1e 100644 --- a/source/blender/io/usd/intern/usd_writer_material.cc +++ b/source/blender/io/usd/intern/usd_writer_material.cc @@ -60,7 +60,6 @@ static const pxr::TfToken out("out", pxr::TfToken::Immortal); static const pxr::TfToken normal("normal", pxr::TfToken::Immortal); static const pxr::TfToken ior("ior", pxr::TfToken::Immortal); static const pxr::TfToken file("file", pxr::TfToken::Immortal); -static const pxr::TfToken preview("preview", pxr::TfToken::Immortal); static const pxr::TfToken raw("raw", pxr::TfToken::Immortal); static const pxr::TfToken sRGB("sRGB", pxr::TfToken::Immortal); static const pxr::TfToken sourceColorSpace("sourceColorSpace", pxr::TfToken::Immortal); @@ -124,10 +123,6 @@ void create_usd_preview_surface_material(const USDExporterContext &usd_export_co return; } - /* Define a 'preview' scope beneath the material which will contain the preview shaders. */ - pxr::UsdGeomScope::Define(usd_export_context.stage, - usd_material.GetPath().AppendChild(usdtokens::preview)); - /* Default map when creating UV primvar reader shaders. */ pxr::TfToken default_uv_sampler = default_uv.empty() ? cyclestokens::UVMap : pxr::TfToken(default_uv); @@ -470,9 +465,8 @@ static pxr::UsdShadeShader create_usd_preview_shader(const USDExporterContext &u const char *name, const int type) { - pxr::SdfPath shader_path = material.GetPath() - .AppendChild(usdtokens::preview) - .AppendChild(pxr::TfToken(pxr::TfMakeValidIdentifier(name))); + pxr::SdfPath shader_path = material.GetPath().AppendChild( + pxr::TfToken(pxr::TfMakeValidIdentifier(name))); pxr::UsdShadeShader shader = pxr::UsdShadeShader::Define(usd_export_context.stage, shader_path); switch (type) { diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index 7f3444d88f4..62656c902d0 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -350,7 +350,8 @@ void USDGenericMeshWriter::assign_materials(const HierarchyContext &context, * which is why we always bind the first material to the entire mesh. See * https://github.com/PixarAnimationStudios/USD/issues/542 for more info. */ bool mesh_material_bound = false; - pxr::UsdShadeMaterialBindingAPI material_binding_api(usd_mesh.GetPrim()); + auto mesh_prim = usd_mesh.GetPrim(); + pxr::UsdShadeMaterialBindingAPI material_binding_api(mesh_prim); for (int mat_num = 0; mat_num < context.object->totcol; mat_num++) { Material *material = BKE_object_material_get(context.object, mat_num + 1); if (material == nullptr) { @@ -369,7 +370,13 @@ void USDGenericMeshWriter::assign_materials(const HierarchyContext &context, break; } - if (!mesh_material_bound) { + if (mesh_material_bound) { + /* USD will require that prims with material bindings have the MaterialBindingAPI applied + * schema. While Bind() above will create the binding attribute, Apply() needs to be called as + * well to add the MaterialBindingAPI schema to the prim itself.*/ + material_binding_api.Apply(mesh_prim); + } + else { /* Blender defaults to double-sided, but USD to single-sided. */ usd_mesh.CreateDoubleSidedAttr(pxr::VtValue(true)); } @@ -396,7 +403,11 @@ void USDGenericMeshWriter::assign_materials(const HierarchyContext &context, pxr::UsdGeomSubset usd_face_subset = material_binding_api.CreateMaterialBindSubset( material_name, face_indices); - pxr::UsdShadeMaterialBindingAPI(usd_face_subset.GetPrim()).Bind(usd_material); + auto subset_prim = usd_face_subset.GetPrim(); + auto subset_material_api = pxr::UsdShadeMaterialBindingAPI(subset_prim); + subset_material_api.Bind(usd_material); + /* Apply the MaterialBindingAPI applied schema, as required by USD.*/ + subset_material_api.Apply(subset_prim); } } diff --git a/source/blender/io/usd/tests/usd_export_test.cc b/source/blender/io/usd/tests/usd_export_test.cc index c34ab7cd6f7..36ff45ccf7a 100644 --- a/source/blender/io/usd/tests/usd_export_test.cc +++ b/source/blender/io/usd/tests/usd_export_test.cc @@ -294,7 +294,7 @@ TEST_F(UsdExportTest, usd_export_material) const std::string prim_name = pxr::TfMakeValidIdentifier(bsdf_node->name); const pxr::UsdPrim bsdf_prim = stage->GetPrimAtPath( - pxr::SdfPath("/_materials/Material/preview/" + prim_name)); + pxr::SdfPath("/_materials/Material/" + prim_name)); compare_blender_node_to_usd_prim(bsdf_node, bsdf_prim); @@ -305,7 +305,7 @@ TEST_F(UsdExportTest, usd_export_material) const std::string image_prim_name = pxr::TfMakeValidIdentifier(image_node->name); const pxr::UsdPrim image_prim = stage->GetPrimAtPath( - pxr::SdfPath("/_materials/Material/preview/" + image_prim_name)); + pxr::SdfPath("/_materials/Material/" + image_prim_name)); ASSERT_TRUE(bool(image_prim)) << "Unable to find Material prim from exported stage " << output_filename; _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs