[Bf-blender-cvs] [2e32a0871fb] universal-scene-description: USD IO: material import improvements

Michael Kowalski noreply at git.blender.org
Mon Aug 30 20:14:44 CEST 2021


Commit: 2e32a0871fb8cfbe55994e54d400e9450e278b66
Author: Michael Kowalski
Date:   Mon Aug 30 14:09:17 2021 -0400
Branches: universal-scene-description
https://developer.blender.org/rB2e32a0871fb8cfbe55994e54d400e9450e278b66

USD IO: material import improvements

UDIM texture support on UsdPreviewSurface import.
New Material Name Collision option for sepcifying behavior when
an imported material name conflicts with the name of an
existing material. Also includes format fixes.

===================================================================

M	source/blender/editors/io/io_usd.c
M	source/blender/io/usd/intern/usd_light_convert.cc
M	source/blender/io/usd/intern/usd_reader_material.cc
M	source/blender/io/usd/intern/usd_reader_mesh.cc
M	source/blender/io/usd/intern/usd_reader_prim.h
M	source/blender/io/usd/intern/usd_writer_material.cc
M	source/blender/io/usd/intern/usd_writer_transform.cc
M	source/blender/io/usd/usd.h

===================================================================

diff --git a/source/blender/editors/io/io_usd.c b/source/blender/editors/io/io_usd.c
index d827442636e..abcc1955318 100644
--- a/source/blender/editors/io/io_usd.c
+++ b/source/blender/editors/io/io_usd.c
@@ -100,8 +100,16 @@ const EnumPropertyItem rna_enum_usd_import_shaders_mode_items_no_umm[] = {
 };
 
 const EnumPropertyItem rna_enum_usd_xform_op_mode_items[] = {
-    {USD_XFORM_OP_SRT, "SRT", 0, "Scale, Rotate, Translate", "Export scale, rotate, and translate Xform operators"},
-    {USD_XFORM_OP_SOT, "SOT", 0, "Scale, Orient, Translate", "Export scale, orient, and translate Xform operators"},
+    {USD_XFORM_OP_SRT,
+     "SRT",
+     0,
+     "Scale, Rotate, Translate",
+     "Export scale, rotate, and translate Xform operators"},
+    {USD_XFORM_OP_SOT,
+     "SOT",
+     0,
+     "Scale, Orient, Translate",
+     "Export scale, orient, and translate Xform operators"},
     {USD_XFORM_OP_MAT, "MAT", 0, "Matrix", "Export matrix operator"},
     {0, NULL, 0, NULL, NULL},
 };
@@ -126,6 +134,20 @@ const EnumPropertyItem prop_usd_export_global_up[] = {
     {0, NULL, 0, NULL, NULL},
 };
 
+const EnumPropertyItem rna_enum_usd_mtl_name_collision_mode_items[] = {
+    {USD_MTL_NAME_COLLISION_MODIFY,
+     "MODIFY",
+     0,
+     "Modify",
+     "Create a unique name for the imported material"},
+    {USD_MTL_NAME_COLLISION_SKIP,
+     "SKIP",
+     0,
+     "Skip",
+     "Keep the existing material and discard the imported material"},
+    {0, NULL, 0, NULL, NULL},
+};
+
 /* Stored in the wmOperator's customdata field to indicate it should run as a background job.
  * This is set when the operator is invoked, and not set when it is only executed. */
 enum { AS_BACKGROUND_JOB = 1 };
@@ -813,11 +835,11 @@ void WM_OT_usd_export(struct wmOperatorType *ot)
       "connected to a background shader, with an optional vector multiply of the texture color.");
 
   RNA_def_enum(ot->srna,
-    "xform_op_mode",
-    rna_enum_usd_xform_op_mode_items,
-    USD_XFORM_OP_SRT,
-    "Xform Ops",
-    "The type of transform operators to write");
+               "xform_op_mode",
+               rna_enum_usd_xform_op_mode_items,
+               USD_XFORM_OP_SRT,
+               "Xform Ops",
+               "The type of transform operators to write");
 }
 
 /* ====== USD Import ====== */
@@ -901,6 +923,9 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
 
   const bool create_background_shader = RNA_boolean_get(op->ptr, "create_background_shader");
 
+  const eUSDMtlNameCollisionMode mtl_name_collision_mode = RNA_enum_get(op->ptr,
+                                                                        "mtl_name_collision_mode");
+
   /* TODO(makowalski): Add support for sequences. */
   const bool is_sequence = false;
   int offset = 0;
@@ -942,7 +967,8 @@ static int wm_usd_import_exec(bContext *C, wmOperator *op)
                                    .apply_unit_conversion_scale = apply_unit_conversion_scale,
                                    .convert_light_from_nits = convert_light_from_nits,
                                    .scale_light_radius = scale_light_radius,
-                                   .create_background_shader = create_background_shader};
+                                   .create_background_shader = create_background_shader,
+                                   .mtl_name_collision_mode = mtl_name_collision_mode};
 
   const bool ok = USD_import(C, filename, &params, as_background_job);
 
@@ -989,6 +1015,7 @@ static void wm_usd_import_draw(bContext *UNUSED(C), wmOperator *op)
   uiItemR(box, ptr, "convert_light_from_nits", 0, NULL, ICON_NONE);
   uiItemR(box, ptr, "scale_light_radius", 0, NULL, ICON_NONE);
   uiItemR(box, ptr, "create_background_shader", 0, NULL, ICON_NONE);
+  uiItemR(box, ptr, "mtl_name_collision_mode", 0, NULL, ICON_NONE);
 
   box = uiLayoutBox(layout);
   col = uiLayoutColumnWithHeading(box, true, IFACE_("Experimental"));
@@ -1161,6 +1188,14 @@ void WM_OT_usd_import(struct wmOperatorType *ot)
                   true,
                   "Create Background Shader",
                   "Convert USD dome lights to world background shaders");
+
+  RNA_def_enum(
+      ot->srna,
+      "mtl_name_collision_mode",
+      rna_enum_usd_mtl_name_collision_mode_items,
+      USD_MTL_NAME_COLLISION_MODIFY,
+      "Material Name Collision",
+      "Behavior when the name of an imported material conflicts with an existing material");
 }
 
 #endif /* WITH_USD */
diff --git a/source/blender/io/usd/intern/usd_light_convert.cc b/source/blender/io/usd/intern/usd_light_convert.cc
index 156540aaec3..649d1bb9294 100644
--- a/source/blender/io/usd/intern/usd_light_convert.cc
+++ b/source/blender/io/usd/intern/usd_light_convert.cc
@@ -39,9 +39,9 @@
 #include "BKE_node.h"
 #include "BKE_scene.h"
 #include "BLI_listbase.h"
+#include "BLI_math.h"
 #include "BLI_path_util.h"
 #include "BLI_string.h"
-#include "BLI_math.h"
 #include "DNA_light_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_world_types.h"
diff --git a/source/blender/io/usd/intern/usd_reader_material.cc b/source/blender/io/usd/intern/usd_reader_material.cc
index ea729bca615..3eae2919070 100644
--- a/source/blender/io/usd/intern/usd_reader_material.cc
+++ b/source/blender/io/usd/intern/usd_reader_material.cc
@@ -26,12 +26,15 @@
 #include "BKE_material.h"
 #include "BKE_node.h"
 
+#include "BLI_fileops.h"
 #include "BLI_math_vector.h"
+#include "BLI_path_util.h"
 #include "BLI_string.h"
 
 #include "DNA_material_types.h"
 
 #include <pxr/base/gf/vec3f.h>
+#include <pxr/usd/ar/resolver.h>
 #include <pxr/usd/usdShade/material.h>
 #include <pxr/usd/usdShade/shader.h>
 
@@ -111,6 +114,62 @@ static void link_nodes(
   nodeAddLink(ntree, source, source_socket, dest, dest_socket);
 }
 
+static pxr::SdfLayerHandle get_layer_handle(const pxr::UsdAttribute &Attribute)
+{
+  for (auto PropertySpec : Attribute.GetPropertyStack(pxr::UsdTimeCode::EarliestTime())) {
+    if (PropertySpec->HasDefaultValue() ||
+        PropertySpec->GetLayer()->GetNumTimeSamplesForPath(PropertySpec->GetPath()) > 0) {
+      return PropertySpec->GetLayer();
+    }
+  }
+
+  return pxr::SdfLayerHandle();
+}
+
+static void add_udim_tiles(Image *image)
+{
+  if (!image || strlen(image->filepath) == 0) {
+    return;
+  }
+
+  char filename[FILE_MAX], dirname[FILE_MAXDIR];
+  BLI_split_dirfile(image->filepath, dirname, filename, sizeof(dirname), sizeof(filename));
+
+  ushort digits;
+  char base_head[FILE_MAX], base_tail[FILE_MAX];
+  int id = BLI_path_sequence_decode(filename, base_head, base_tail, &digits);
+
+  if (id != 1001) {
+    return;
+  }
+
+  image->source = IMA_SRC_TILED;
+
+  struct direntry *dir;
+  uint totfile = BLI_filelist_dir_contents(dirname, &dir);
+
+  for (int i = 0; i < totfile; i++) {
+    if (!(dir[i].type & S_IFREG)) {
+      continue;
+    }
+    char head[FILE_MAX], tail[FILE_MAX];
+    id = BLI_path_sequence_decode(dir[i].relname, head, tail, &digits);
+
+    if (digits > 4 || !(STREQLEN(base_head, head, FILE_MAX)) ||
+        !(STREQLEN(base_tail, tail, FILE_MAX))) {
+      continue;
+    }
+
+    if (id < 1001 || id >= IMA_UDIM_MAX) {
+      continue;
+    }
+
+    BKE_image_add_tile(image, id, nullptr);
+  }
+
+  BLI_filelist_free(dir, totfile);
+}
+
 /* Returns true if the given shader may have opacity < 1.0, based
  * on heuristics. */
 static bool needs_blend(const pxr::UsdShadeShader &usd_shader)
@@ -627,7 +686,26 @@ void USDMaterialReader::load_tex_image(const pxr::UsdShadeShader &usd_shader,
   }
 
   const pxr::SdfAssetPath &asset_path = file_val.Get<pxr::SdfAssetPath>();
+
   std::string file_path = asset_path.GetResolvedPath();
+
+  bool have_udim = false;
+
+  if (file_path.empty()) {
+    file_path = asset_path.GetAssetPath();
+
+    /* Check if we have a UDIM path. */
+    std::size_t udim_token_offset = file_path.find("<UDIM>");
+
+    if (udim_token_offset != std::string::npos) {
+      have_udim = true;
+      file_path.replace(udim_token_offset, 6, "1001");
+      if (pxr::SdfLayerHandle layer_handle = get_layer_handle(file_input.GetAttr())) {
+        file_path = layer_handle->ComputeAbsolutePath(file_path);
+      }
+    }
+  }
+
   if (file_path.empty()) {
     std::cerr << "WARNING: Couldn't resolve image asset '" << asset_path
               << "' for Texture Image node." << std::endl;
@@ -635,13 +713,19 @@ void USDMaterialReader::load_tex_image(const pxr::UsdShadeShader &usd_shader,
   }
 
   const char *im_file = file_path.c_str();
+
   Image *image = BKE_image_load_exists(bmain_, im_file);
+
   if (!image) {
     std::cerr << "WARNING: Couldn't open image file '" << im_file << "' for Texture Image node."
               << std::endl;
     return;
   }
 
+  if (have_udim) {
+    add_udim_tiles(image);
+  }
+
   tex_image->id = &image->id;
 
   /* Set texture color space.
diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc
index f13da4680e2..cc5a542625b 100644
--- a/source/blender/io/usd/intern/usd_reader_mesh.cc
+++ b/source/blender/io/usd/intern/usd_reader_mesh.cc
@@ -80,41 +80,61 @@ static void assign_materials(Main *bmain,
                              Object *ob,
                              const std::map<pxr::SdfPath, int> &mat_index_map,
                              const USDImportParams &params,
-                             pxr::UsdStageRefPtr stage)
+                             pxr::UsdStageRefPtr stage,
+                             std::map<std::string, std::string> &usd_path_to_mat_name)
 {
   if (!(stage && bmain && ob)) {
     return;
   }
 
-  bool can_assign = true;
   std::map<pxr::SdfPath, int>::const_iterator it = mat_index_map.begin();
 
-  int matcount = 0;
-  for (; it != mat_index_map.end(); ++it, matcount++) {
+  for (; it != mat_index_map.end(); ++it) {
     if (!BKE_object_material_slot_add(bmain, ob)) {
-      can_assign = false;
-      break;
+      std::cout << "WARNING: couldn't create slot for material " << it->first << " on object "
+                << ob->id.name << std::endl;
+      return;
     }
   }
 
-  if (!can_assign) {
-    return;
-  }
-
-  /* TODO(kevin): use global map? */
+  /* TODO(makowalski): use global map? */
   std::map<std::string, Materia

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list