[Bf-blender-cvs] [b67b84bd5d6] master: Fix T103984: USD exports pass usdchecker

Michael Kowalski noreply at git.blender.org
Fri Jan 27 16:30:59 CET 2023


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;



More information about the Bf-blender-cvs mailing list