[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