[Bf-blender-cvs] [14a84d76e88] sybren-usd: USD: Experimental support for instancing/referencing

Sybren A. Stüvel noreply at git.blender.org
Fri Jul 19 11:15:27 CEST 2019


Commit: 14a84d76e880572ff93318c1d543bb193413ce98
Author: Sybren A. Stüvel
Date:   Thu Jul 18 12:44:48 2019 +0200
Branches: sybren-usd
https://developer.blender.org/rB14a84d76e880572ff93318c1d543bb193413ce98

USD: Experimental support for instancing/referencing

Dupli-object meshes are now written to USD as references to the origina
mesh. This is still very limited in correctness, as there are issues
referencing to materials from a referenced mesh.

I am still committing this, as it also introduces some code clarifications
and gives us a place to start when continuing the quest for proper
instancing in USD.

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

M	source/blender/editors/io/io_usd.c
M	source/blender/usd/intern/abstract_hierarchy_iterator.cc
M	source/blender/usd/intern/abstract_hierarchy_iterator.h
M	source/blender/usd/intern/usd_writer_mesh.cc
M	source/blender/usd/usd.h

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

diff --git a/source/blender/editors/io/io_usd.c b/source/blender/editors/io/io_usd.c
index 529a330ca14..71c65eef4f6 100644
--- a/source/blender/editors/io/io_usd.c
+++ b/source/blender/editors/io/io_usd.c
@@ -102,6 +102,7 @@ static int wm_usd_export_exec(bContext *C, wmOperator *op)
   const bool visible_objects_only = RNA_boolean_get(op->ptr, "visible_objects_only");
   const bool export_animation = RNA_boolean_get(op->ptr, "export_animation");
   const bool export_hair = RNA_boolean_get(op->ptr, "export_hair");
+  const bool use_instancing = RNA_boolean_get(op->ptr, "use_instancing");
   const bool evaluation_mode = RNA_enum_get(op->ptr, "evaluation_mode");
 
   struct USDExportParams params = {
@@ -109,6 +110,7 @@ static int wm_usd_export_exec(bContext *C, wmOperator *op)
       export_hair,
       selected_objects_only,
       visible_objects_only,
+      use_instancing,
       evaluation_mode,
   };
 
@@ -154,6 +156,13 @@ void WM_OT_usd_export(struct wmOperatorType *ot)
   RNA_def_boolean(
       ot->srna, "export_hair", false, "Export Hair", "When true, hair is exported as USD curves");
 
+  RNA_def_boolean(ot->srna,
+                  "use_instancing",
+                  false,
+                  "Use Instancing (EXPERIMENTAL)",
+                  "When true, dupli-objects are written as instances of the original in USD. "
+                  "Experimental feature, not working perfectly");
+
   RNA_def_enum(ot->srna,
                "evaluation_mode",
                rna_enum_usd_export_evaluation_mode_items,
diff --git a/source/blender/usd/intern/abstract_hierarchy_iterator.cc b/source/blender/usd/intern/abstract_hierarchy_iterator.cc
index b8a6dcad548..d0492b76d30 100644
--- a/source/blender/usd/intern/abstract_hierarchy_iterator.cc
+++ b/source/blender/usd/intern/abstract_hierarchy_iterator.cc
@@ -38,6 +38,19 @@ bool HierarchyContext::operator<(const HierarchyContext &other) const
   return export_parent < other.export_parent;
 }
 
+bool HierarchyContext::is_instance() const
+{
+  return !original_export_path.empty();
+}
+void HierarchyContext::mark_as_instance_of(const std::string &reference_export_path)
+{
+  original_export_path = reference_export_path;
+}
+void HierarchyContext::mark_as_not_instanced()
+{
+  original_export_path.clear();
+}
+
 AbstractHierarchyIterator::AbstractHierarchyIterator(Depsgraph *depsgraph)
     : depsgraph(depsgraph), writers()
 {
@@ -80,15 +93,21 @@ void AbstractHierarchyIterator::debug_print_export_graph() const
     total_graph_size += map_iter.second.size();
     for (HierarchyContext *child_ctx : map_iter.second) {
       if (child_ctx->duplicator == nullptr) {
-        printf("       - %s%s\n",
+        printf("       - %s%s%s\n",
                child_ctx->object->id.name + 2,
-               child_ctx->weak_export ? " \033[97m(weak)\033[0m" : "");
+               child_ctx->weak_export ? " \033[97m(weak)\033[0m" : "",
+               child_ctx->original_export_path.size() ?
+                   (std::string("ref ") + child_ctx->original_export_path).c_str() :
+                   "");
       }
       else {
-        printf("       - %s (dup by %s%s)\n",
+        printf("       - %s (dup by %s%s) %s\n",
                child_ctx->object->id.name + 2,
                child_ctx->duplicator->id.name + 2,
-               child_ctx->weak_export ? ", \033[97mweak\033[0m" : "");
+               child_ctx->weak_export ? ", \033[97mweak\033[0m" : "",
+               child_ctx->original_export_path.size() ?
+                   (std::string("ref ") + child_ctx->original_export_path).c_str() :
+                   "");
       }
     }
   }
@@ -99,6 +118,8 @@ void AbstractHierarchyIterator::iterate()
 {
   export_graph_construct();
   export_graph_prune();
+  determine_export_paths(HierarchyContext::root());
+  determine_duplication_references(HierarchyContext::root(), "");
   make_writers(HierarchyContext::root());
   export_graph_clear();
 }
@@ -167,6 +188,7 @@ void AbstractHierarchyIterator::visit_object(Object *object,
   context->weak_export = weak_export;
   context->animation_check_include_parent = false;
   context->export_path = "";
+  context->original_export_path = "";
   copy_m4_m4(context->matrix_world, object->obmat);
 
   export_graph[std::make_pair(export_parent, nullptr)].insert(context);
@@ -191,6 +213,7 @@ void AbstractHierarchyIterator::visit_dupli_object(DupliObject *dupli_object,
   context->duplicator = duplicator;
   context->weak_export = false;
   context->export_path = "";
+  context->original_export_path = "";
 
   /* If the dupli-object's scene parent is also instanced by this object, use that as the
    * export parent. Otherwise use the dupli-parent as export parent. */
@@ -212,10 +235,6 @@ void AbstractHierarchyIterator::visit_dupli_object(DupliObject *dupli_object,
   context->animation_check_include_parent = animation_check_include_parent;
   copy_m4_m4(context->matrix_world, dupli_object->mat);
 
-  std::string export_parent_name = context->export_parent ?
-                                       get_object_name(context->export_parent) :
-                                       "/";
-
   // Construct export name for the dupli-instance.
   std::stringstream suffix_stream;
   suffix_stream << std::hex;
@@ -226,6 +245,9 @@ void AbstractHierarchyIterator::visit_dupli_object(DupliObject *dupli_object,
 
   export_graph[graph_index].insert(context);
 
+  // std::string export_parent_name = context->export_parent ?
+  //                                      get_object_name(context->export_parent) :
+  //                                      "/";
   // printf("    DU %30s %p (export-parent=%s; duplicator = %s; world x = %f)\n",
   //        context->export_name.c_str(),
   //        context->object,
@@ -284,12 +306,78 @@ void AbstractHierarchyIterator::export_graph_clear()
 }
 
 AbstractHierarchyIterator::ExportGraph::mapped_type &AbstractHierarchyIterator::graph_children(
-    const HierarchyContext *parent_context)
+    const HierarchyContext *context)
 {
-  Object *parent_object = parent_context ? parent_context->object : nullptr;
-  Object *parent_duplicator = parent_context ? parent_context->duplicator : nullptr;
+  if (context == nullptr) {
+    return export_graph[std::make_pair(nullptr, nullptr)];
+  }
 
-  return export_graph[std::make_pair(parent_object, parent_duplicator)];
+  return export_graph[std::make_pair(context->object, context->duplicator)];
+}
+
+void AbstractHierarchyIterator::determine_export_paths(const HierarchyContext *parent_context)
+{
+  const std::string &parent_export_path = parent_context ? parent_context->export_path : "";
+
+  for (HierarchyContext *context : graph_children(parent_context)) {
+    context->export_path = path_concatenate(parent_export_path, context->export_name);
+
+    if (context->duplicator == nullptr) {
+      /* This is an original object, so we should keep track of where it was exported to, just in
+       * case it gets duplicated somewhere. */
+      ID *orig_ob = &context->object->id;
+      originals_export_paths[orig_ob] = context->export_path;
+
+      if (context->object->data != nullptr) {
+        ID *object_data = static_cast<ID *>(context->object->data);
+        ID *orig_data = object_data;
+        originals_export_paths[orig_data] = get_object_data_path(context);
+      }
+    }
+
+    determine_export_paths(context);
+  }
+}
+
+void AbstractHierarchyIterator::determine_duplication_references(
+    const HierarchyContext *parent_context, std::string indent)
+{
+  ExportGraph::mapped_type children = graph_children(parent_context);
+
+  for (HierarchyContext *context : children) {
+    if (context->duplicator != nullptr) {
+      ID *orig_id = &context->object->id;
+      const ExportPathMap::const_iterator &it = originals_export_paths.find(orig_id);
+
+      if (it == originals_export_paths.end()) {
+        // The original was not found, so mark this instance as "the original".
+        context->mark_as_not_instanced();
+        originals_export_paths[orig_id] = context->export_path;
+      }
+      else {
+        context->mark_as_instance_of(it->second);
+      }
+
+      if (context->object->data) {
+        ID *orig_data_id = (ID *)context->object->data;
+        const ExportPathMap::const_iterator &it = originals_export_paths.find(orig_data_id);
+
+        if (it == originals_export_paths.end()) {
+          // The original was not found, so mark this instance as "original".
+          std::string data_path = get_object_data_path(context);
+          // printf(
+          //     "%s\033[93mUSD issue\033[0m: %s is DATA instance of %p, but no original DATA path
+          //     " "is known\n", indent.c_str(), data_path.c_str(), orig_data_id);
+
+          context->mark_as_not_instanced();
+          originals_export_paths[orig_id] = context->export_path;
+          originals_export_paths[orig_data_id] = data_path;
+        }
+      }
+    }
+
+    determine_duplication_references(context, indent + "  ");
+  }
 }
 
 void AbstractHierarchyIterator::make_writers(const HierarchyContext *parent_context)
@@ -307,16 +395,8 @@ void AbstractHierarchyIterator::make_writers(const HierarchyContext *parent_cont
   const std::string &parent_export_path = parent_context ? parent_context->export_path : "";
 
   for (HierarchyContext *context : graph_children(parent_context)) {
-    std::string export_path = path_concatenate(parent_export_path, context->export_name);
-    context->export_path = export_path;
     copy_m4_m4(context->parent_matrix_inv_world, parent_matrix_inv_world);
 
-    // printf("'%s' + '%s' = '%s' (exporting object %s)\n",
-    //        parent_export_path.c_str(),
-    //        context->export_name.c_str(),
-    //        export_path.c_str(),
-    //        context->object->id.name + 2);
-
     // Get or create the transform writer.
     xform_writer = ensure_writer(context, &AbstractHierarchyIterator::create_xform_writer);
     if (xform_writer == nullptr) {
@@ -381,13 +461,19 @@ void AbstractHierarchyIterator::make_writer_object_data(const HierarchyContext *
   }
 
   HierarchyContext data_context = *context;
-  ID *object_data = static_cast<ID *>(context->object->data);
-  std::string data_path = path_conca

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list