[Bf-blender-cvs] [c5197cdf4bc] sybren-usd: USD: Fixed issue with mesh particle export

Sybren A. Stüvel noreply at git.blender.org
Tue Jul 16 15:33:42 CEST 2019


Commit: c5197cdf4bcc1ca34a9b0e745732a42fee1b4442
Author: Sybren A. Stüvel
Date:   Tue Jul 16 12:44:47 2019 +0200
Branches: sybren-usd
https://developer.blender.org/rBc5197cdf4bcc1ca34a9b0e745732a42fee1b4442

USD: Fixed issue with mesh particle export

When mesh particles were exported, the object name was still used for each
instance of that object. As such, only one instance was written to USD.
This is now fixed by suffixing the object name with the particle's
persistent ID, giving each particle XForm a unique name.

Particles are still only written when they are alive, which means that they
are always visible (there is currently no code that deals with marking them
as invisible outside their lifespan).

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

M	source/blender/usd/intern/abstract_hierarchy_iterator.cc
M	source/blender/usd/intern/abstract_hierarchy_iterator.h
M	source/blender/usd/intern/usd_hierarchy_iterator.cc
M	source/blender/usd/intern/usd_hierarchy_iterator.h
M	source/blender/usd/intern/usd_writer_transform.cc

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

diff --git a/source/blender/usd/intern/abstract_hierarchy_iterator.cc b/source/blender/usd/intern/abstract_hierarchy_iterator.cc
index b8cbe8b64f7..2bd368de221 100644
--- a/source/blender/usd/intern/abstract_hierarchy_iterator.cc
+++ b/source/blender/usd/intern/abstract_hierarchy_iterator.cc
@@ -1,5 +1,8 @@
 #include "abstract_hierarchy_iterator.h"
 
+#include <iostream>
+#include <limits.h>
+#include <sstream>
 #include <string>
 
 extern "C" {
@@ -23,6 +26,19 @@ const HierarchyContext &HierarchyContext::root()
   return root_hierarchy_context;
 }
 
+bool HierarchyContext::operator<(const HierarchyContext &other) const
+{
+  if (object != other.object) {
+    return object < other.object;
+  }
+  if (duplicator != NULL && duplicator == other.duplicator) {
+    // Only resort to string comparisons when both objects are created by the same duplicator.
+    return export_name < other.export_name;
+  }
+
+  return export_parent < other.export_parent;
+}
+
 AbstractHierarchyIterator::AbstractHierarchyIterator(Depsgraph *depsgraph)
     : depsgraph(depsgraph), writers()
 {
@@ -180,6 +196,7 @@ void AbstractHierarchyIterator::visit_object(Object *object,
 {
   HierarchyContext context;
   context.object = object;
+  context.export_name = get_object_name(object);
   context.export_parent = export_parent;
   context.duplicator = nullptr;
   context.weak_export = weak_export;
@@ -192,7 +209,7 @@ void AbstractHierarchyIterator::visit_object(Object *object,
 
   // std::string export_parent_name = export_parent ? get_object_name(export_parent) : "/";
   // printf("    OB %30s %p (export-parent=%s; world x = %f)\n",
-  //        get_object_name(context.object).c_str(),
+  //        context.export_name.c_str(),
   //        context.object,
   //        export_parent_name.c_str(),
   //        context.matrix_world[3][0]);
@@ -232,11 +249,21 @@ 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;
+  for (int i = 0; i < MAX_DUPLI_RECUR && dupli_object->persistent_id[i] != INT_MAX; i++) {
+    suffix_stream << "-" << dupli_object->persistent_id[i];
+  }
+  context.export_name = make_valid_name(get_object_name(context.object) + suffix_stream.str());
+
   export_graph[graph_index].insert(context);
 
-  // std::string export_parent_name = export_parent ? get_object_name(export_parent) : "/";
   // printf("    DU %30s %p (export-parent=%s; duplicator = %s; world x = %f)\n",
-  //        get_object_name(context.object).c_str(),
+  //        context.export_name.c_str(),
   //        context.object,
   //        export_parent_name.c_str(),
   //        duplicator->id.name + 2,
@@ -291,19 +318,21 @@ void AbstractHierarchyIterator::make_writers(const HierarchyContext &parent_cont
     invert_m4_m4(parent_matrix_inv_world, parent_context.matrix_world);
   }
 
-  for (HierarchyContext context :
-       export_graph[std::make_pair(parent_context.object, parent_context.duplicator)]) {
-    std::string export_path = path_concatenate(parent_context.export_path,
-                                               get_object_name(context.object));
+  ExportGraph::mapped_type &graph_children =
+      export_graph[std::make_pair(parent_context.object, parent_context.duplicator)];
+  for (HierarchyContext context : graph_children) {
+    BLI_assert(!context.export_name.empty());
+
+    std::string export_path = path_concatenate(parent_context.export_path, context.export_name);
     context.parent_writer = parent_writer;
     context.export_path = export_path;
     copy_m4_m4(context.parent_matrix_inv_world, parent_matrix_inv_world);
 
-    // const char *color = context.duplicator ? "32;1" : "30";
-    // printf("%s \033[%sm%s\033[0m\n",
+    // printf("'%s' + '%s' = '%s' (exporting object %s)\n",
+    //        parent_context.export_path.c_str(),
+    //        context.export_name.c_str(),
     //        export_path.c_str(),
-    //        color,
-    //        context.duplicator ? context.duplicator->id.name + 2 : "");
+    //        context.object->id.name + 2);
 
     // Get or create the transform writer.
     xform_writer = ensure_writer(context, &AbstractHierarchyIterator::create_xform_writer);
@@ -402,7 +431,12 @@ std::string AbstractHierarchyIterator::get_id_name(const ID *id) const
     return "";
   }
 
-  return std::string(id->name + 2);
+  return make_valid_name(std::string(id->name + 2));
+}
+
+std::string AbstractHierarchyIterator::make_valid_name(const std::string &name) const
+{
+  return name;
 }
 
 std::string AbstractHierarchyIterator::path_concatenate(const std::string &parent_path,
diff --git a/source/blender/usd/intern/abstract_hierarchy_iterator.h b/source/blender/usd/intern/abstract_hierarchy_iterator.h
index 00b5ba4a425..3280644fa3e 100644
--- a/source/blender/usd/intern/abstract_hierarchy_iterator.h
+++ b/source/blender/usd/intern/abstract_hierarchy_iterator.h
@@ -56,6 +56,7 @@ struct HierarchyContext {
   Object *export_parent;
   Object *duplicator;
   float matrix_world[4][4];
+  std::string export_name;
 
   /* When true, the object will be exported only as transform, and only if is an ancestor of a
    * non-weak child: */
@@ -72,10 +73,7 @@ struct HierarchyContext {
   ParticleSystem *particle_system;         // Only set for particle/hair writers.
 
   // For making the struct insertable into a std::set<>.
-  bool operator<(const HierarchyContext &other) const
-  {
-    return object < other.object;
-  }
+  bool operator<(const HierarchyContext &other) const;
 
   /* Return a HierarchyContext representing the root of the export hierarchy. */
   static const HierarchyContext &root();
@@ -107,7 +105,8 @@ class AbstractHierarchyIterator {
   const WriterMap &writer_map() const;
   void release_writers();
 
-  virtual std::string get_id_name(const ID *id) const = 0;
+  virtual std::string get_id_name(const ID *id) const;
+  virtual std::string make_valid_name(const std::string &name) const;
 
  private:
   void construct_export_graph();
diff --git a/source/blender/usd/intern/usd_hierarchy_iterator.cc b/source/blender/usd/intern/usd_hierarchy_iterator.cc
index 3cae06536a5..364e82cb145 100644
--- a/source/blender/usd/intern/usd_hierarchy_iterator.cc
+++ b/source/blender/usd/intern/usd_hierarchy_iterator.cc
@@ -46,10 +46,8 @@ void USDHierarchyIterator::delete_object_writer(AbstractHierarchyWriter *writer)
   delete static_cast<USDAbstractWriter *>(writer);
 }
 
-std::string USDHierarchyIterator::get_id_name(const ID *const id) const
+std::string USDHierarchyIterator::make_valid_name(const std::string &name) const
 {
-  BLI_assert(id != nullptr);
-  std::string name(id->name + 2);
   return pxr::TfMakeValidIdentifier(name);
 }
 
diff --git a/source/blender/usd/intern/usd_hierarchy_iterator.h b/source/blender/usd/intern/usd_hierarchy_iterator.h
index 5cbb40f6348..a83c3a128fb 100644
--- a/source/blender/usd/intern/usd_hierarchy_iterator.h
+++ b/source/blender/usd/intern/usd_hierarchy_iterator.h
@@ -28,7 +28,7 @@ class USDHierarchyIterator : public AbstractHierarchyIterator {
   void set_export_frame(float frame_nr);
   const pxr::UsdTimeCode &get_export_time_code() const;
 
-  virtual std::string get_id_name(const ID *const id) const override;
+  virtual std::string make_valid_name(const std::string &name) const override;
 
  protected:
   virtual bool should_export_object(const Object *object) const override;
diff --git a/source/blender/usd/intern/usd_writer_transform.cc b/source/blender/usd/intern/usd_writer_transform.cc
index 4abeac491a4..5bce1caa6fd 100644
--- a/source/blender/usd/intern/usd_writer_transform.cc
+++ b/source/blender/usd/intern/usd_writer_transform.cc
@@ -52,5 +52,11 @@ static bool check_is_transform_animated(Object *object, bool recurse_parent)
 
 bool USDTransformWriter::check_is_animated(const HierarchyContext &context) const
 {
+  if (context.duplicator != NULL) {
+    /* This object is being duplicated, so could be emitted by a particle system and thus
+     * influenced by forces. TODO(Sybren): Make this more strict. Probably better to get from the
+     * depsgraph whether this object instance has a time source. */
+    return true;
+  }
   return check_is_transform_animated(context.object, context.animation_check_include_parent);
 }



More information about the Bf-blender-cvs mailing list