[Bf-blender-cvs] [dca907005ac] usd-importer-T81257-merge: USD Import: merge prim with parent xform.

makowalski noreply at git.blender.org
Sat Apr 24 03:17:24 CEST 2021


Commit: dca907005ac9258677e31e59f4b685ceb73ebadc
Author: makowalski
Date:   Fri Apr 23 21:08:33 2021 -0400
Branches: usd-importer-T81257-merge
https://developer.blender.org/rBdca907005ac9258677e31e59f4b685ceb73ebadc

USD Import: merge prim with parent xform.

Added logic to merge a USD prim and its parent
Xform into a single Blender object representation.
Added a USDXformReader::use_parent_xform_ flag
which, if true, causes the USDXformReader to
use the parent of the encapsulated prim to compute
the object's transform.

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

M	source/blender/io/usd/intern/usd_reader_stage.cc
M	source/blender/io/usd/intern/usd_reader_xform.cc
M	source/blender/io/usd/intern/usd_reader_xform.h

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

diff --git a/source/blender/io/usd/intern/usd_reader_stage.cc b/source/blender/io/usd/intern/usd_reader_stage.cc
index 180de601dd6..fc015199900 100644
--- a/source/blender/io/usd/intern/usd_reader_stage.cc
+++ b/source/blender/io/usd/intern/usd_reader_stage.cc
@@ -176,11 +176,48 @@ static bool _prune_by_purpose(const pxr::UsdGeomImageable &imageable,
   return false;
 }
 
+/* Determine if the given reader can use the parent of the encapsulated USD prim
+ * to compute the Blender object's transform. If so, the reader is appropriately
+ * flagged and the function returns true. Otherwise, the function returns false. */
+static bool _merge_with_parent(USDPrimReader *reader)
+{
+  USDXformReader *xform_reader = dynamic_cast<USDXformReader *>(reader);
+
+  if (!xform_reader) {
+    return false;
+  }
+
+  /* Check if the Xform reader is already merged. */
+  if (xform_reader->use_parent_xform()) {
+    return false;
+  }
+
+  /* Only merge if the parent is an Xform. */
+  if (!xform_reader->prim().GetParent().IsA<pxr::UsdGeomXform>()) {
+    return false;
+  }
+
+  /* Don't merge Xform and Scope prims. */
+  if (xform_reader->prim().IsA<pxr::UsdGeomXform>() ||
+      xform_reader->prim().IsA<pxr::UsdGeomScope>()) {
+    return false;
+  }
+
+  /* Don't merge if the prim has authored transform ops. */
+  if (xform_reader->prim_has_xform_ops()) {
+    return false;
+  }
+
+  /* Flag the Xform reader as merged. */
+  xform_reader->set_use_parent_xform(true);
+
+  return true;
+}
+
 static USDPrimReader *_handlePrim(Main *bmain,
                                   pxr::UsdStageRefPtr stage,
                                   const USDImportParams &params,
                                   pxr::UsdPrim prim,
-                                  USDPrimReader *parent_reader,
                                   std::vector<USDPrimReader *> &readers,
                                   const ImportSettings &settings)
 {
@@ -196,35 +233,51 @@ static USDPrimReader *_handlePrim(Main *bmain,
     }
   }
 
-  USDPrimReader *reader = NULL;
+  pxr::Usd_PrimFlagsPredicate filter_predicate = pxr::UsdPrimDefaultPredicate;
 
-  // This check prevents the stage pseudo 'root' prim
-  // or the root prims of scenegraph 'master' prototypes
-  // from being added.
-  if (!(prim.IsPseudoRoot() || prim.IsMaster())) {
-    reader = USDStageReader::create_reader(prim, params, settings);
+  if (params.import_instance_proxies) {
+    filter_predicate = pxr::UsdTraverseInstanceProxies(filter_predicate);
+  }
 
-    if (reader == NULL) {
-      return NULL;
-    }
+  pxr::UsdPrimSiblingRange children = prim.GetFilteredChildren(filter_predicate);
 
-    reader->parent(parent_reader);
-    reader->create_object(bmain, 0.0);
+  std::vector<USDPrimReader *> child_readers;
 
-    readers.push_back(reader);
-    reader->incref();
+  for (const auto &childPrim : children) {
+    USDPrimReader *child_reader = _handlePrim(bmain, stage, params, childPrim, readers, settings);
+    if (child_reader) {
+      child_readers.push_back(child_reader);
+    }
   }
 
-  pxr::Usd_PrimFlagsPredicate filter_predicate = pxr::UsdPrimDefaultPredicate;
+  /* Check if we can merge an Xform with its child prim. */
+  if (child_readers.size() == 1) {
 
-  if (params.import_instance_proxies) {
-    filter_predicate = pxr::UsdTraverseInstanceProxies(filter_predicate);
+    USDPrimReader *child_reader = child_readers.front();
+
+    if (_merge_with_parent(child_reader)) {
+      return child_reader;
+    }
   }
 
-  pxr::UsdPrimSiblingRange children = prim.GetFilteredChildren(filter_predicate);
+  USDPrimReader *reader = nullptr;
 
-  for (const auto &childPrim : children) {
-    _handlePrim(bmain, stage, params, childPrim, reader, readers, settings);
+  if (!prim.IsPseudoRoot()) {
+    reader = USDStageReader::create_reader(prim, params, settings);
+
+    if (reader == nullptr) {
+      return nullptr;
+    }
+
+    reader->create_object(bmain, 0.0);
+
+    readers.push_back(reader);
+    reader->incref();
+
+    /* Set each child reader's parent. */
+    for (USDPrimReader *child_reader : child_readers) {
+      child_reader->parent(reader);
+    }
   }
 
   return reader;
@@ -262,7 +315,7 @@ void USDStageReader::collect_readers(Main *bmain,
   }
 
   stage_->SetInterpolationType(pxr::UsdInterpolationType::UsdInterpolationTypeHeld);
-  _handlePrim(bmain, stage_, params, root, NULL, readers_, settings);
+  _handlePrim(bmain, stage_, params, root, readers_, settings);
 }
 
 void USDStageReader::clear_readers(bool decref)
diff --git a/source/blender/io/usd/intern/usd_reader_xform.cc b/source/blender/io/usd/intern/usd_reader_xform.cc
index 16c6ee4c0f6..46f8331c3c7 100644
--- a/source/blender/io/usd/intern/usd_reader_xform.cc
+++ b/source/blender/io/usd/intern/usd_reader_xform.cc
@@ -66,7 +66,11 @@ void USDXformReader::read_object_data(Main * /* bmain */, const double motionSam
     bConstraint *con = BKE_constraint_add_for_object(
         object_, NULL, CONSTRAINT_TYPE_TRANSFORM_CACHE);
     bTransformCacheConstraint *data = static_cast<bTransformCacheConstraint *>(con->data);
-    BLI_strncpy(data->object_path, prim_.GetPath().GetText(), FILE_MAX);
+
+    std::string prim_path = use_parent_xform_ ? prim_.GetParent().GetPath().GetAsString() :
+                                                prim_path_;
+
+    BLI_strncpy(data->object_path, prim_path.c_str(), FILE_MAX);
 
     data->cache_file = settings_->cache_file;
     id_us_plus(&data->cache_file->id);
@@ -83,7 +87,14 @@ void USDXformReader::read_matrix(float r_mat[4][4] /* local matrix */,
   is_constant = true;
   unit_m4(r_mat);
 
-  pxr::UsdGeomXformable xformable(prim_);
+  pxr::UsdGeomXformable xformable;
+
+  if (use_parent_xform_) {
+    xformable = pxr::UsdGeomXformable(prim_.GetParent());
+  }
+  else {
+    xformable = pxr::UsdGeomXformable(prim_);
+  }
 
   if (!xformable) {
     // This might happen if the prim is a Scope.
@@ -116,6 +127,20 @@ void USDXformReader::read_matrix(float r_mat[4][4] /* local matrix */,
   }
 }
 
+bool USDXformReader::prim_has_xform_ops() const
+{
+  pxr::UsdGeomXformable xformable(prim_);
+
+  if (!xformable) {
+    // This might happen if the prim is a Scope.
+    return false;
+  }
+
+  bool reset_xform_stack = false;
+
+  return !xformable.GetOrderedXformOps(&reset_xform_stack).empty();
+}
+
 bool USDXformReader::is_root_xform_object() const
 {
   // It's not sufficient to check for a null parent to determine
diff --git a/source/blender/io/usd/intern/usd_reader_xform.h b/source/blender/io/usd/intern/usd_reader_xform.h
index 197451c680b..4afc994157b 100644
--- a/source/blender/io/usd/intern/usd_reader_xform.h
+++ b/source/blender/io/usd/intern/usd_reader_xform.h
@@ -21,12 +21,14 @@
 namespace blender::io::usd {
 
 class USDXformReader : public USDPrimReader {
+ private:
+  bool use_parent_xform_;
 
  public:
   USDXformReader(const pxr::UsdPrim &prim,
                  const USDImportParams &import_params,
                  const ImportSettings &settings)
-      : USDPrimReader(prim, import_params, settings)
+      : USDPrimReader(prim, import_params, settings), use_parent_xform_(false)
   {
   }
 
@@ -35,6 +37,17 @@ class USDXformReader : public USDPrimReader {
 
   void read_matrix(float r_mat[4][4], const float time, const float scale, bool &is_constant);
 
+  bool use_parent_xform() const
+  {
+    return use_parent_xform_;
+  }
+  void set_use_parent_xform(bool flag)
+  {
+    use_parent_xform_ = flag;
+  }
+
+  bool prim_has_xform_ops() const;
+
   // Returns true if this reader represents an object that is the root of the
   // transform hierarchy.
   bool is_root_xform_object() const;



More information about the Bf-blender-cvs mailing list